From 405e36f2199dc99e7b2ada6fb1e48c5daa5399a2 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Fri, 17 Jun 2022 12:40:00 +0000 Subject: [PATCH 001/235] Putting source back into Dev Mode --- CHANGELOG.md | 2 ++ cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e06d1a251e..bb723833f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.45.0 (June 17, 2022) IMPROVEMENTS: diff --git a/cli/version/version.go b/cli/version/version.go index 67a1cd371e..475688852a 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 67a1cd371e..475688852a 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 36ce81878579aaa16d9c5929fc32ea56a677c4e1 Mon Sep 17 00:00:00 2001 From: John Murret Date: Fri, 17 Jun 2022 14:16:08 -0600 Subject: [PATCH 002/235] Updating retry from 10 to 60 seconds for cloud clean up because of AKS failure. (#1291) * Updating retry from 10 to 60 seconds for cloud clean up because of AKS failure. * Update acceptance/framework/consul/helm_cluster.go Co-authored-by: Kyle Schochenmaier Co-authored-by: Kyle Schochenmaier --- acceptance/framework/consul/helm_cluster.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index 151f0c852a..a6530c205b 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -201,9 +201,9 @@ func (h *HelmCluster) Destroy(t *testing.T) { } } } - // Retry a few times because sometimes certain resources (like PVC) take time to delete + // Retry because sometimes certain resources (like PVC) take time to delete // in cloud providers. - retry.RunWith(&retry.Counter{Wait: 1 * time.Second, Count: 10}, t, func(r *retry.R) { + retry.RunWith(&retry.Counter{Wait: 1 * time.Second, Count: 600}, t, func(r *retry.R) { // Verify all Consul Pods are deleted. pods, err = h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) require.NoError(r, err) From b9452e659c488b5c86bff02e3d58155df93e4579 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Mon, 20 Jun 2022 09:54:20 -0600 Subject: [PATCH 003/235] Bring back basic acceptance tests cases (#1293) --- acceptance/tests/basic/basic_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/acceptance/tests/basic/basic_test.go b/acceptance/tests/basic/basic_test.go index b01c795b70..c82368dcdd 100644 --- a/acceptance/tests/basic/basic_test.go +++ b/acceptance/tests/basic/basic_test.go @@ -23,18 +23,18 @@ func TestBasicInstallation(t *testing.T) { secure bool autoEncrypt bool }{ - // { - // false, - // false, - // }, + { + false, + false, + }, { true, false, }, - // { - // true, - // true, - // }, + { + true, + true, + }, } for _, c := range cases { From 88a46752a6f3c234c67b6f5a85e33f9affa5256d Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Mon, 20 Jun 2022 16:53:25 -0700 Subject: [PATCH 004/235] changelog for peering --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb723833f1..cddc301f6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,20 @@ ## UNRELEASED ## 0.45.0 (June 17, 2022) +FEATURES: +* [Experimental] Cluster Peering: Support Consul cluster peering, which allows service connectivity between two independent clusters. + [[GH-1273](https://github.com/hashicorp/consul-k8s/pull/1273)] + + Enabling peering will deploy the peering controllers and PeeringAcceptor and PeeringDialer CRDs. The new CRDs are used + to establish a peering connection between two clusters. + + See the [Cluster Peering on Kubernetes](https://www.consul.io/docs/connect/cluster-peering/k8s) + for full instructions. + + Requirements: + * Consul 1.13+ + * `global.peering.enabled=true` and `connectInject.enabled=true` must be set to enable peering. + * Mesh gateways are required for service to service communication across peers, i.e `meshGateway.enabled=true`. IMPROVEMENTS: * Helm From 15001a67e7a0e6c96731e647996ef50848be71f2 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 23 Jun 2022 11:27:31 -0500 Subject: [PATCH 005/235] Add acceptance tests matrix tests for consul nightlies (#1238) * Add acceptance tests matrix for consul nightlies which test latest consul-k8s release with consul-1.11 and 1.12 nightlies. --- .circleci/config.yml | 86 ++++++++++++++++++++++++++- acceptance/framework/config/config.go | 2 + acceptance/framework/flags/flags.go | 3 + 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 88d3aff594..04a55b41e0 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -864,7 +864,79 @@ jobs: path: /tmp/test-results - slack/status: fail_only: true - failure_message: "Acceptance tests against Kind with Kubernetes v1.22 failed. Check the logs at: ${CIRCLE_BUILD_URL}" + failure_message: "Acceptance tests against Kind with Kubernetes v1.23 failed. Check the logs at: ${CIRCLE_BUILD_URL}" + + acceptance-kind-1-23-consul-nightly-1-11: + environment: + - TEST_RESULTS: /tmp/test-results + - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul:1.11-dev" + - ENVOY_IMAGE: "envoyproxy/envoy:1.20.2" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.44.0" + machine: + image: ubuntu-2004:202010-01 + resource_class: xlarge + steps: + - checkout + - install-prereqs + - create-kind-clusters: + version: "v1.23.0" + - restore_cache: + keys: + - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + - run: + name: go mod download + working_directory: *acceptance-mod-path + command: go mod download + - save_cache: + key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + paths: + - ~/.go_workspace/pkg/mod + - run: mkdir -p $TEST_RESULTS + - run-acceptance-tests: + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11-dev" -envoy-image=$ENVOY_IMAGE + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + - slack/status: + fail_only: true + failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.11.x nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" + + acceptance-kind-1-23-consul-nightly-1-12: + environment: + - TEST_RESULTS: /tmp/test-results + - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul:1.12-dev" + - ENVOY_IMAGE: "envoyproxy/envoy:1.22.2" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.44.0" + machine: + image: ubuntu-2004:202010-01 + resource_class: xlarge + steps: + - checkout + - install-prereqs + - create-kind-clusters: + version: "v1.23.0" + - restore_cache: + keys: + - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + - run: + name: go mod download + working_directory: *acceptance-mod-path + command: go mod download + - save_cache: + key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + paths: + - ~/.go_workspace/pkg/mod + - run: mkdir -p $TEST_RESULTS + - run-acceptance-tests: + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12-dev" -envoy-image=$ENVOY_IMAGE + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + - slack/status: + fail_only: true + failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.12 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" workflows: version: 2 @@ -929,3 +1001,15 @@ workflows: - acceptance-kind-1-23: requires: - dev-upload-docker + + nightly-acceptance-tests-consul: + triggers: + - schedule: + cron: "0 0 * * *" + filters: + branches: + only: + - main + jobs: + - acceptance-kind-1-23-consul-nightly-1-11 + - acceptance-kind-1-23-consul-nightly-1-12 diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index 5ae92544ac..1bda173025 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -43,6 +43,7 @@ type TestConfig struct { ConsulImage string ConsulK8SImage string ConsulVersion *version.Version + EnvoyImage string NoCleanupOnFailure bool DebugDirectory string @@ -84,6 +85,7 @@ func (t *TestConfig) HelmValuesFromConfig() (map[string]string, error) { setIfNotEmpty(helmValues, "global.image", t.ConsulImage) setIfNotEmpty(helmValues, "global.imageK8S", t.ConsulK8SImage) + setIfNotEmpty(helmValues, "global.imageEnvoy", t.EnvoyImage) return helmValues, nil } diff --git a/acceptance/framework/flags/flags.go b/acceptance/framework/flags/flags.go index 425cdf4935..6565c2413d 100644 --- a/acceptance/framework/flags/flags.go +++ b/acceptance/framework/flags/flags.go @@ -32,6 +32,7 @@ type TestFlags struct { flagConsulImage string flagConsulK8sImage string flagConsulVersion string + flagEnvoyImage string flagNoCleanupOnFailure bool @@ -59,6 +60,7 @@ func (t *TestFlags) init() { flag.StringVar(&t.flagConsulImage, "consul-image", "", "The Consul image to use for all tests.") flag.StringVar(&t.flagConsulK8sImage, "consul-k8s-image", "", "The consul-k8s image to use for all tests.") flag.StringVar(&t.flagConsulVersion, "consul-version", "", "The consul version used for all tests.") + flag.StringVar(&t.flagEnvoyImage, "envoy-image", "", "The Envoy image to use for all tests.") flag.BoolVar(&t.flagEnableMultiCluster, "enable-multi-cluster", false, "If true, the tests that require multiple Kubernetes clusters will be run. "+ @@ -141,6 +143,7 @@ func (t *TestFlags) TestConfigFromFlags() *config.TestConfig { ConsulImage: t.flagConsulImage, ConsulK8SImage: t.flagConsulK8sImage, ConsulVersion: consulVersion, + EnvoyImage: t.flagEnvoyImage, NoCleanupOnFailure: t.flagNoCleanupOnFailure, DebugDirectory: tempDir, From b69edac9352d9d6239ce63dac92eb3e7200bcb4c Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Thu, 23 Jun 2022 12:58:09 -0400 Subject: [PATCH 006/235] Add watchers for Peering Token secrets for the peering controllers (#1284) - When a Kubernetes secret that has a label indicating it is a peering token secret, the controllers watch those secrets and updated to those secrets re-enqueues the resource that is associated with that peering token secret. The status is used to determine the Peering Acceptor that is re-enqueued while the spec is used to determing the Peering Dialer that gets re-enqueued. This is because the acceptor is responsible for creating the secret and hence metaphorically owns the secret described in it's status. OTOH the dialer should respond to changes in the secret described in it's spec. This is only supported for secrets with a Kubernetes backend. --- control-plane/connect-inject/annotations.go | 4 + .../peering_acceptor_controller.go | 51 +++- .../peering_acceptor_controller_test.go | 276 ++++++++++++++++++ .../peering_dialer_controller.go | 48 ++- .../peering_dialer_controller_test.go | 274 +++++++++++++++++ 5 files changed, 651 insertions(+), 2 deletions(-) diff --git a/control-plane/connect-inject/annotations.go b/control-plane/connect-inject/annotations.go index f615637470..1c3c9420e4 100644 --- a/control-plane/connect-inject/annotations.go +++ b/control-plane/connect-inject/annotations.go @@ -146,6 +146,10 @@ const ( // registered with Consul. labelServiceIgnore = "consul.hashicorp.com/service-ignore" + // labelPeeringToken is a label that can be added to a secret to allow it to be watched + // by the peering controllers. + labelPeeringToken = "consul.hashicorp.com/peering-token" + // injected is used as the annotation value for annotationInjected. injected = "injected" diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index ca14b2f89c..8830546aed 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -14,8 +14,13 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" ) // PeeringAcceptorController reconciles a PeeringAcceptor object. @@ -318,7 +323,11 @@ func (r *PeeringAcceptorController) deleteK8sSecret(ctx context.Context, accepto func (r *PeeringAcceptorController) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&consulv1alpha1.PeeringAcceptor{}). - Complete(r) + Watches( + &source.Kind{Type: &corev1.Secret{}}, + handler.EnqueueRequestsFromMapFunc(r.requestsForPeeringTokens), + builder.WithPredicates(predicate.NewPredicateFuncs(r.filterPeeringAcceptors)), + ).Complete(r) } // generateToken is a helper function that calls the Consul api to generate a token for the peer. @@ -344,12 +353,52 @@ func (r *PeeringAcceptorController) deletePeering(ctx context.Context, peerName return nil } +// requestsForPeeringTokens creates a slice of requests for the peering acceptor controller. +// It enqueues a request for each acceptor that needs to be reconciled. It iterates through +// the list of acceptors and creates a request for the acceptor that has the same secret as it's +// secretRef and that of the updated secret that is being watched. +// We compare it to the secret in the status as the resource has created the secret. +func (r *PeeringAcceptorController) requestsForPeeringTokens(object client.Object) []reconcile.Request { + r.Log.Info("received update for Peering Token Secret", "name", object.GetName(), "namespace", object.GetNamespace()) + + // Get the list of all acceptors. + var acceptorList consulv1alpha1.PeeringAcceptorList + if err := r.Client.List(r.Context, &acceptorList); err != nil { + r.Log.Error(err, "failed to list Peering Acceptors") + return []ctrl.Request{} + } + for _, acceptor := range acceptorList.Items { + if acceptor.SecretRef().Backend == "kubernetes" { + if acceptor.SecretRef().Name == object.GetName() && acceptor.Namespace == object.GetNamespace() { + return []ctrl.Request{{NamespacedName: types.NamespacedName{Namespace: acceptor.Namespace, Name: acceptor.Name}}} + } + } + } + return []ctrl.Request{} +} + +// filterPeeringAcceptors receives meta and object information for Kubernetes resources that are being watched, +// which in this case are Secrets. It only returns true if the Secret is a Peering Token Secret. It reads the labels +// from the meta of the resource and uses the values of the "consul.hashicorp.com/peering-token" label to validate that +// the Secret is a Peering Token Secret. +func (r *PeeringAcceptorController) filterPeeringAcceptors(object client.Object) bool { + secretLabels := object.GetLabels() + isPeeringToken, ok := secretLabels[labelPeeringToken] + if !ok { + return false + } + return isPeeringToken == "true" +} + // createSecret is a helper function that creates a corev1.Secret when provided inputs. func createSecret(name, namespace, key, value string) *corev1.Secret { secret := &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: name, Namespace: namespace, + Labels: map[string]string{ + labelPeeringToken: "true", + }, }, Data: map[string][]byte{ key: []byte(value), diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index 65ccfba0ad..1f53bcc516 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -21,6 +21,7 @@ import ( "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/reconcile" ) // TestReconcileCreateUpdatePeeringAcceptor creates a peering acceptor. @@ -396,6 +397,8 @@ func TestReconcileCreateUpdatePeeringAcceptor(t *testing.T) { require.NoError(t, err) expSecrets := tt.expectedK8sSecrets() require.Equal(t, expSecrets[0].Name, createdSecret.Name) + require.Contains(t, createdSecret.Labels, labelPeeringToken) + require.Equal(t, createdSecret.Labels[labelPeeringToken], "true") // This assertion needs to be on StringData rather than Data because in the fake K8s client the contents are // stored in StringData if that's how the secret was initialized in the fake client. In a real cluster, this // StringData is an input only field, and shouldn't be read from. @@ -943,3 +946,276 @@ func TestAcceptorUpdateStatusError(t *testing.T) { }) } } + +func TestAcceptor_FilterPeeringAcceptor(t *testing.T) { + t.Parallel() + cases := map[string]struct { + secret *corev1.Secret + result bool + }{ + "returns true if label is set to true": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + labelPeeringToken: "true", + }, + }, + }, + result: true, + }, + "returns false if label is set to false": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + labelPeeringToken: "false", + }, + }, + }, + result: false, + }, + "returns false if label is set to a non-true value": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + labelPeeringToken: "foo", + }, + }, + }, + result: false, + }, + "returns false if label is not set": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + result: false, + }, + } + + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + controller := PeeringAcceptorController{} + result := controller.filterPeeringAcceptors(tt.secret) + require.Equal(t, tt.result, result) + }) + } +} + +func TestAcceptor_RequestsForPeeringTokens(t *testing.T) { + t.Parallel() + cases := map[string]struct { + secret *corev1.Secret + acceptors v1alpha1.PeeringAcceptorList + result []reconcile.Request + }{ + "secret matches existing acceptor": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + acceptors: v1alpha1.PeeringAcceptorList{ + Items: []v1alpha1.PeeringAcceptor{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering", + Namespace: "test", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Namespace: "test", + Name: "peering", + }, + }, + }, + }, + "does not match if backend is not kubernetes": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + acceptors: v1alpha1.PeeringAcceptorList{ + Items: []v1alpha1.PeeringAcceptor{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering", + Namespace: "test", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "vault", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{}, + }, + "only matches with the correct acceptor": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + acceptors: v1alpha1.PeeringAcceptorList{ + Items: []v1alpha1.PeeringAcceptor{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-1", + Namespace: "test", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-2", + Namespace: "test-2", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-3", + Namespace: "test", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test-2", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Namespace: "test", + Name: "peering-1", + }, + }, + }, + }, + "can match with zero acceptors": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + acceptors: v1alpha1.PeeringAcceptorList{ + Items: []v1alpha1.PeeringAcceptor{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-1", + Namespace: "test", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "fest", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-2", + Namespace: "test-2", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-3", + Namespace: "test", + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "test-2", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{}, + }, + } + + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + s := scheme.Scheme + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringAcceptor{}, &v1alpha1.PeeringAcceptorList{}) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(tt.secret, &tt.acceptors).Build() + controller := PeeringAcceptorController{ + Client: fakeClient, + Log: logrtest.TestLogger{T: t}, + } + result := controller.requestsForPeeringTokens(tt.secret) + + require.Equal(t, tt.result, result) + }) + } +} diff --git a/control-plane/connect-inject/peering_dialer_controller.go b/control-plane/connect-inject/peering_dialer_controller.go index 5ca50c8442..1a62ae1b91 100644 --- a/control-plane/connect-inject/peering_dialer_controller.go +++ b/control-plane/connect-inject/peering_dialer_controller.go @@ -14,8 +14,13 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" ) // PeeringDialerController reconciles a PeeringDialer object. @@ -231,7 +236,11 @@ func (r *PeeringDialerController) getSecret(ctx context.Context, name string, na func (r *PeeringDialerController) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&consulv1alpha1.PeeringDialer{}). - Complete(r) + Watches( + &source.Kind{Type: &corev1.Secret{}}, + handler.EnqueueRequestsFromMapFunc(r.requestsForPeeringTokens), + builder.WithPredicates(predicate.NewPredicateFuncs(r.filterPeeringDialers)), + ).Complete(r) } // establishPeering is a helper function that calls the Consul api to generate a token for the peer. @@ -257,3 +266,40 @@ func (r *PeeringDialerController) deletePeering(ctx context.Context, peerName st } return nil } + +// requestsForPeeringTokens creates a slice of requests for the peering dialer controller. +// It enqueues a request for each dialer that needs to be reconciled. It iterates through +// the list of dialers and creates a request for the dialer that has the same secret as it's +// secret and that of the updated secret that is being watched. +// We compare it to the secret in the spec as the resource is dependent on the secret. +func (r *PeeringDialerController) requestsForPeeringTokens(object client.Object) []reconcile.Request { + r.Log.Info("received update for Peering Token Secret", "name", object.GetName(), "namespace", object.GetNamespace()) + + // Get the list of all dialers. + var dialerList consulv1alpha1.PeeringDialerList + if err := r.Client.List(r.Context, &dialerList); err != nil { + r.Log.Error(err, "failed to list PeeringDialers") + return []ctrl.Request{} + } + for _, dialer := range dialerList.Items { + if dialer.Secret().Backend == "kubernetes" { + if dialer.Secret().Name == object.GetName() && dialer.Namespace == object.GetNamespace() { + return []ctrl.Request{{NamespacedName: types.NamespacedName{Namespace: dialer.Namespace, Name: dialer.Name}}} + } + } + } + return []ctrl.Request{} +} + +// filterPeeringAcceptors receives meta and object information for Kubernetes resources that are being watched, +// which in this case are Secrets. It only returns true if the Secret is a Peering Token Secret. It reads the labels +// from the meta of the resource and uses the values of the "consul.hashicorp.com/peering-token" label to validate that +// the Secret is a Peering Token Secret. +func (r *PeeringDialerController) filterPeeringDialers(object client.Object) bool { + secretLabels := object.GetLabels() + isPeeringToken, ok := secretLabels[labelPeeringToken] + if !ok { + return false + } + return isPeeringToken == "true" +} diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index 4b453fce94..4715840500 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -23,6 +23,7 @@ import ( "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/reconcile" ) // TestReconcileCreateUpdatePeeringDialer creates a peering dialer. @@ -781,3 +782,276 @@ func TestDialerUpdateStatusError(t *testing.T) { }) } } + +func TestDialer_FilterPeeringDialers(t *testing.T) { + t.Parallel() + cases := map[string]struct { + secret *corev1.Secret + result bool + }{ + "returns true if label is set to true": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + labelPeeringToken: "true", + }, + }, + }, + result: true, + }, + "returns false if label is set to false": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + labelPeeringToken: "false", + }, + }, + }, + result: false, + }, + "returns false if label is set to a non-true value": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + labelPeeringToken: "foo", + }, + }, + }, + result: false, + }, + "returns false if label is not set": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + result: false, + }, + } + + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + controller := PeeringDialerController{} + result := controller.filterPeeringDialers(tt.secret) + require.Equal(t, tt.result, result) + }) + } +} + +func TestDialer_RequestsForPeeringTokens(t *testing.T) { + t.Parallel() + cases := map[string]struct { + secret *corev1.Secret + dialers v1alpha1.PeeringDialerList + result []reconcile.Request + }{ + "secret matches existing acceptor": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + dialers: v1alpha1.PeeringDialerList{ + Items: []v1alpha1.PeeringDialer{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering", + Namespace: "test", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Namespace: "test", + Name: "peering", + }, + }, + }, + }, + "does not match if backend is not kubernetes": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + dialers: v1alpha1.PeeringDialerList{ + Items: []v1alpha1.PeeringDialer{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering", + Namespace: "test", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "vault", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{}, + }, + "only matches with the correct dialer": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + dialers: v1alpha1.PeeringDialerList{ + Items: []v1alpha1.PeeringDialer{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-1", + Namespace: "test", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-2", + Namespace: "test-2", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-3", + Namespace: "test", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test-2", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Namespace: "test", + Name: "peering-1", + }, + }, + }, + }, + "can match with zero dialer": { + secret: &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + }, + }, + dialers: v1alpha1.PeeringDialerList{ + Items: []v1alpha1.PeeringDialer{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-1", + Namespace: "test", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "fest", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-2", + Namespace: "test-2", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "peering-3", + Namespace: "test", + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "test-2", + Key: "test", + Backend: "kubernetes", + }, + }, + }, + }, + }, + }, + result: []reconcile.Request{}, + }, + } + + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + s := scheme.Scheme + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringDialer{}, &v1alpha1.PeeringDialerList{}) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(tt.secret, &tt.dialers).Build() + controller := PeeringDialerController{ + Client: fakeClient, + Log: logrtest.TestLogger{T: t}, + } + result := controller.requestsForPeeringTokens(tt.secret) + + require.Equal(t, tt.result, result) + }) + } +} From 7e494487b311aac7ac78c5b8b8649af97f5fe438 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Thu, 23 Jun 2022 14:09:43 -0400 Subject: [PATCH 007/235] Add support for version annotation on Peering Dialer and Acceptor. (#1302) --- CHANGELOG.md | 5 + .../templates/crd-peeringacceptors.yaml | 5 + .../consul/templates/crd-peeringdialers.yaml | 5 + .../api/v1alpha1/peeringacceptor_types.go | 6 +- .../api/v1alpha1/peeringdialer_types.go | 6 +- .../api/v1alpha1/zz_generated.deepcopy.go | 10 + ...consul.hashicorp.com_peeringacceptors.yaml | 5 + .../consul.hashicorp.com_peeringdialers.yaml | 5 + control-plane/connect-inject/annotations.go | 4 + .../connect-inject/container_init.go | 5 + .../peering_acceptor_controller.go | 20 ++ .../peering_acceptor_controller_test.go | 229 +++++++++++++++- .../peering_dialer_controller.go | 43 ++- .../peering_dialer_controller_test.go | 252 +++++++++++++++++- 14 files changed, 583 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cddc301f6d..21c40a9c93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## UNRELEASED +FEATURES: +* [Experimental] Cluster Peering: + * Add support for secret watchers on the Peering Acceptor and Peering Dialer controllers. [[GH-1284](https://github.com/hashicorp/consul-k8s/pull/1284)] + * Add support for version annotation on the Peering Acceptor and Peering Dialer controllers. [[GH-1302](https://github.com/hashicorp/consul-k8s/pull/1302)] + ## 0.45.0 (June 17, 2022) FEATURES: * [Experimental] Cluster Peering: Support Consul cluster peering, which allows service connectivity between two independent clusters. diff --git a/charts/consul/templates/crd-peeringacceptors.yaml b/charts/consul/templates/crd-peeringacceptors.yaml index a5242ad311..6cd7090ef7 100644 --- a/charts/consul/templates/crd-peeringacceptors.yaml +++ b/charts/consul/templates/crd-peeringacceptors.yaml @@ -71,6 +71,11 @@ spec: description: LastReconcileTime is the last time the resource was reconciled. format: date-time type: string + latestPeeringVersion: + description: LatestPeeringVersion is the latest version of the resource + that was reconciled. + format: int64 + type: integer reconcileError: description: ReconcileError shows any errors during the last reconciliation of this resource. diff --git a/charts/consul/templates/crd-peeringdialers.yaml b/charts/consul/templates/crd-peeringdialers.yaml index f03a1790ad..d5dee45f61 100644 --- a/charts/consul/templates/crd-peeringdialers.yaml +++ b/charts/consul/templates/crd-peeringdialers.yaml @@ -71,6 +71,11 @@ spec: description: LastReconcileTime is the last time the resource was reconciled. format: date-time type: string + latestPeeringVersion: + description: LatestPeeringVersion is the latest version of the resource + that was reconciled. + format: int64 + type: integer reconcileError: description: ReconcileError shows any errors during the last reconciliation of this resource. diff --git a/control-plane/api/v1alpha1/peeringacceptor_types.go b/control-plane/api/v1alpha1/peeringacceptor_types.go index f6dd84c4e8..5dd70b0597 100644 --- a/control-plane/api/v1alpha1/peeringacceptor_types.go +++ b/control-plane/api/v1alpha1/peeringacceptor_types.go @@ -33,8 +33,6 @@ type PeeringAcceptorList struct { // PeeringAcceptorSpec defines the desired state of PeeringAcceptor. type PeeringAcceptorSpec struct { - // Important: Run "make" to regenerate code after modifying this file - // Peer describes the information needed to create a peering. Peer *Peer `json:"peer"` } @@ -55,8 +53,8 @@ type Secret struct { // PeeringAcceptorStatus defines the observed state of PeeringAcceptor. type PeeringAcceptorStatus struct { - // Important: Run "make" to regenerate code after modifying this file - + // LatestPeeringVersion is the latest version of the resource that was reconciled. + LatestPeeringVersion *uint64 `json:"latestPeeringVersion,omitempty"` // LastReconcileTime is the last time the resource was reconciled. // +optional LastReconcileTime *metav1.Time `json:"lastReconcileTime,omitempty" description:"last time the resource was reconciled"` diff --git a/control-plane/api/v1alpha1/peeringdialer_types.go b/control-plane/api/v1alpha1/peeringdialer_types.go index 99385ff0aa..0ffea7bee4 100644 --- a/control-plane/api/v1alpha1/peeringdialer_types.go +++ b/control-plane/api/v1alpha1/peeringdialer_types.go @@ -33,16 +33,14 @@ type PeeringDialerList struct { // PeeringDialerSpec defines the desired state of PeeringDialer. type PeeringDialerSpec struct { - // Important: Run "make" to regenerate code after modifying this file - // Peer describes the information needed to create a peering. Peer *Peer `json:"peer"` } // PeeringDialerStatus defines the observed state of PeeringDialer. type PeeringDialerStatus struct { - // Important: Run "make" to regenerate code after modifying this file - + // LatestPeeringVersion is the latest version of the resource that was reconciled. + LatestPeeringVersion *uint64 `json:"latestPeeringVersion,omitempty"` // LastReconcileTime is the last time the resource was reconciled. // +optional LastReconcileTime *metav1.Time `json:"lastReconcileTime,omitempty" description:"last time the resource was reconciled"` diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index 78b0e33959..4806d72e6b 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -916,6 +916,11 @@ func (in *PeeringAcceptorSpec) DeepCopy() *PeeringAcceptorSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PeeringAcceptorStatus) DeepCopyInto(out *PeeringAcceptorStatus) { *out = *in + if in.LatestPeeringVersion != nil { + in, out := &in.LatestPeeringVersion, &out.LatestPeeringVersion + *out = new(uint64) + **out = **in + } if in.LastReconcileTime != nil { in, out := &in.LastReconcileTime, &out.LastReconcileTime *out = (*in).DeepCopy() @@ -1024,6 +1029,11 @@ func (in *PeeringDialerSpec) DeepCopy() *PeeringDialerSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *PeeringDialerStatus) DeepCopyInto(out *PeeringDialerStatus) { *out = *in + if in.LatestPeeringVersion != nil { + in, out := &in.LatestPeeringVersion, &out.LatestPeeringVersion + *out = new(uint64) + **out = **in + } if in.LastReconcileTime != nil { in, out := &in.LastReconcileTime, &out.LastReconcileTime *out = (*in).DeepCopy() diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml index a4a00a7426..f2df1eb96b 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml @@ -64,6 +64,11 @@ spec: description: LastReconcileTime is the last time the resource was reconciled. format: date-time type: string + latestPeeringVersion: + description: LatestPeeringVersion is the latest version of the resource + that was reconciled. + format: int64 + type: integer reconcileError: description: ReconcileError shows any errors during the last reconciliation of this resource. diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml index c2eef39627..8492acec3a 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml @@ -64,6 +64,11 @@ spec: description: LastReconcileTime is the last time the resource was reconciled. format: date-time type: string + latestPeeringVersion: + description: LatestPeeringVersion is the latest version of the resource + that was reconciled. + format: int64 + type: integer reconcileError: description: ReconcileError shows any errors during the last reconciliation of this resource. diff --git a/control-plane/connect-inject/annotations.go b/control-plane/connect-inject/annotations.go index 1c3c9420e4..777eaa1beb 100644 --- a/control-plane/connect-inject/annotations.go +++ b/control-plane/connect-inject/annotations.go @@ -142,6 +142,10 @@ const ( // webhook/meshWebhook. annotationOriginalPod = "consul.hashicorp.com/original-pod" + // annotationPeeringVersion is the version of the peering resource and can be utilized + // to explicitly perform the peering operation again. + annotationPeeringVersion = "consul.hashicorp.com/peering-version" + // labelServiceIgnore is a label that can be added to a service to prevent it from being // registered with Consul. labelServiceIgnore = "consul.hashicorp.com/service-ignore" diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index 66ab836863..bae4592397 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -326,6 +326,11 @@ func pointerToInt64(i int64) *int64 { return &i } +// pointerToUInt64 takes an int64 and returns a pointer to it. +func pointerToUint64(i uint64) *uint64 { + return &i +} + // pointerToBool takes a bool and returns a pointer to it. func pointerToBool(b bool) *bool { return &b diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index 8830546aed..680dc5cc5f 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -3,6 +3,7 @@ package connectinject import ( "context" "errors" + "strconv" "time" "github.com/go-logr/logr" @@ -214,6 +215,15 @@ func shouldGenerateToken(acceptor *consulv1alpha1.PeeringAcceptor, existingStatu if acceptor.SecretRef().Backend != acceptor.Secret().Backend { return false, false, errors.New("PeeringAcceptor backend cannot be changed") } + if peeringVersionString, ok := acceptor.Annotations[annotationPeeringVersion]; ok { + peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) + if err != nil { + return false, false, err + } + if acceptor.Status.LatestPeeringVersion == nil || *acceptor.Status.LatestPeeringVersion < peeringVersion { + return true, false, nil + } + } // Compare the existing secret resource version. // Get the secret specified by the status, make sure it matches the status' secret.ResourceVersion. if existingStatusSecret != nil { @@ -238,6 +248,16 @@ func (r *PeeringAcceptorController) updateStatus(ctx context.Context, acceptor * Error: pointerToBool(false), Message: pointerToString(""), } + if peeringVersionString, ok := acceptor.Annotations[annotationPeeringVersion]; ok { + peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) + if err != nil { + r.Log.Error(err, "failed to update PeeringAcceptor status", "name", acceptor.Name, "namespace", acceptor.Namespace) + return err + } + if acceptor.Status.LatestPeeringVersion == nil || *acceptor.Status.LatestPeeringVersion < peeringVersion { + acceptor.Status.LatestPeeringVersion = pointerToUint64(peeringVersion) + } + } err := r.Status().Update(ctx, acceptor) if err != nil { r.Log.Error(err, "failed to update PeeringAcceptor status", "name", acceptor.Name, "namespace", acceptor.Namespace) diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index 1f53bcc516..69599f84a5 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -24,8 +24,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -// TestReconcileCreateUpdatePeeringAcceptor creates a peering acceptor. -func TestReconcileCreateUpdatePeeringAcceptor(t *testing.T) { +// TestReconcile_CreateUpdatePeeringAcceptor creates a peering acceptor. +func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { t.Parallel() nodeName := "test-node" cases := []struct { @@ -202,6 +202,69 @@ func TestReconcileCreateUpdatePeeringAcceptor(t *testing.T) { }, initialConsulPeerName: "acceptor-created", }, + { + name: "PeeringAcceptor version annotation is updated", + k8sObjects: func() []runtime.Object { + acceptor := &v1alpha1.PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created", + Namespace: "default", + Annotations: map[string]string{ + annotationPeeringVersion: "2", + }, + }, + Spec: v1alpha1.PeeringAcceptorSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + ResourceVersion: "some-old-sha", + }, + }, + } + secret := createSecret("acceptor-created-secret", "default", "data", "some-old-data") + return []runtime.Object{acceptor, secret} + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + LatestPeeringVersion: pointerToUint64(2), + }, + expectedConsulPeerings: []*api.Peering{ + { + Name: "acceptor-created", + }, + }, + expectedK8sSecrets: func() []*corev1.Secret { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created-secret", + Namespace: "default", + }, + StringData: map[string]string{ + "data": "tokenstub", + }, + } + return []*corev1.Secret{secret} + }, + initialConsulPeerName: "acceptor-created", + }, { name: "PeeringAcceptor status secret exists and there's no peering in Consul", k8sObjects: func() []runtime.Object { @@ -422,6 +485,7 @@ func TestReconcileCreateUpdatePeeringAcceptor(t *testing.T) { require.Equal(t, tt.expectedStatus.SecretRef.Name, acceptor.SecretRef().Name) require.Equal(t, tt.expectedStatus.SecretRef.Key, acceptor.SecretRef().Key) require.Equal(t, tt.expectedStatus.SecretRef.Backend, acceptor.SecretRef().Backend) + require.Equal(t, tt.expectedStatus.LatestPeeringVersion, acceptor.Status.LatestPeeringVersion) } // Check that old secret was deleted. if tt.expectDeletedK8sSecret != nil { @@ -433,14 +497,13 @@ func TestReconcileCreateUpdatePeeringAcceptor(t *testing.T) { t.Error("old secret should have been deleted but was not") } } - }) } } -// TestReconcileDeletePeeringAcceptor reconciles a PeeringAcceptor resource that is no longer in Kubernetes, but still +// TestReconcile_DeletePeeringAcceptor reconciles a PeeringAcceptor resource that is no longer in Kubernetes, but still // exists in Consul. -func TestReconcileDeletePeeringAcceptor(t *testing.T) { +func TestReconcile_DeletePeeringAcceptor(t *testing.T) { // Add the default namespace. ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "default"}} acceptor := &v1alpha1.PeeringAcceptor{ @@ -520,6 +583,162 @@ func TestReconcileDeletePeeringAcceptor(t *testing.T) { require.EqualError(t, err, `secrets "acceptor-deleted" not found`) } +// TestReconcile_AcceptorVersionAnnotation tests the behavior of Reconcile for various +// scenarios involving the user setting the version annotation. +func TestReconcile_VersionAnnotation(t *testing.T) { + t.Parallel() + nodeName := "test-node" + cases := map[string]struct { + annotations map[string]string + expErr string + expectedStatus *v1alpha1.PeeringAcceptorStatus + }{ + "fails if annotation is not a number": { + annotations: map[string]string{ + annotationPeeringVersion: "foo", + }, + expErr: `strconv.ParseUint: parsing "foo": invalid syntax`, + }, + "is no/op if annotation value is less than value in status": { + annotations: map[string]string{ + annotationPeeringVersion: "2", + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + ResourceVersion: "some-old-sha", + }, + LatestPeeringVersion: pointerToUint64(3), + }, + }, + "is no/op if annotation value is equal to value in status": { + annotations: map[string]string{ + annotationPeeringVersion: "3", + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + ResourceVersion: "some-old-sha", + }, + LatestPeeringVersion: pointerToUint64(3), + }, + }, + "updates if annotation value is greater than value in status": { + annotations: map[string]string{ + annotationPeeringVersion: "4", + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + LatestPeeringVersion: pointerToUint64(4), + }, + }, + } + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "default"}} + acceptor := &v1alpha1.PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created", + Namespace: "default", + Annotations: tt.annotations, + }, + Spec: v1alpha1.PeeringAcceptorSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + Status: v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + ResourceVersion: "some-old-sha", + }, + LatestPeeringVersion: pointerToUint64(3), + }, + } + secret := createSecret("acceptor-created-secret", "default", "data", "some-data") + // Create fake k8s client + k8sObjects := []runtime.Object{acceptor, secret, ns} + + s := scheme.Scheme + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringAcceptor{}, &v1alpha1.PeeringAcceptorList{}) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(k8sObjects...).Build() + + // Create test consul server. + consul, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) { + c.NodeName = nodeName + }) + require.NoError(t, err) + defer consul.Stop() + consul.WaitForServiceIntentions(t) + + cfg := &api.Config{ + Address: consul.HTTPAddr, + } + consulClient, err := api.NewClient(cfg) + require.NoError(t, err) + + _, _, err = consulClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: "acceptor-created"}, nil) + require.NoError(t, err) + + // Create the peering acceptor controller + controller := &PeeringAcceptorController{ + Client: fakeClient, + Log: logrtest.TestLogger{T: t}, + ConsulClient: consulClient, + Scheme: s, + } + namespacedName := types.NamespacedName{ + Name: "acceptor-created", + Namespace: "default", + } + + resp, err := controller.Reconcile(context.Background(), ctrl.Request{ + NamespacedName: namespacedName, + }) + if tt.expErr != "" { + require.EqualError(t, err, tt.expErr) + } else { + require.NoError(t, err) + } + require.False(t, resp.Requeue) + + // Get the reconciled PeeringAcceptor and make assertions on the status + acceptor = &v1alpha1.PeeringAcceptor{} + err = fakeClient.Get(context.Background(), namespacedName, acceptor) + require.NoError(t, err) + require.Contains(t, acceptor.Finalizers, FinalizerName) + if tt.expectedStatus != nil { + require.Equal(t, tt.expectedStatus.SecretRef.Name, acceptor.SecretRef().Name) + require.Equal(t, tt.expectedStatus.SecretRef.Key, acceptor.SecretRef().Key) + require.Equal(t, tt.expectedStatus.SecretRef.Backend, acceptor.SecretRef().Backend) + require.Equal(t, tt.expectedStatus.LatestPeeringVersion, acceptor.Status.LatestPeeringVersion) + } + }) + } +} + func TestShouldGenerateToken(t *testing.T) { cases := []struct { name string diff --git a/control-plane/connect-inject/peering_dialer_controller.go b/control-plane/connect-inject/peering_dialer_controller.go index 1a62ae1b91..a5f3e19094 100644 --- a/control-plane/connect-inject/peering_dialer_controller.go +++ b/control-plane/connect-inject/peering_dialer_controller.go @@ -3,6 +3,7 @@ package connectinject import ( "context" "errors" + "strconv" "time" "github.com/go-logr/logr" @@ -161,7 +162,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques // Or, if the peering in Consul does exist, compare it to the spec's secret. If there's any // differences, initiate peering. if r.specStatusSecretsDifferent(dialer, specSecret) { - r.Log.Info("the secret in status.secretRef exists and is different from spec.peer.secret; establishing peering with the existing spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) + r.Log.Info("the version annotation was incremented; re-establishing peering with spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { r.updateStatusError(ctx, dialer, err) @@ -171,6 +172,21 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } } + + if updated, err := r.versionAnnotationUpdated(dialer); err == nil && updated { + r.Log.Info("status.secret exists, but the peering doesn't exist in Consul; establishing peering with the existing spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) + peeringToken := specSecret.Data[dialer.Secret().Key] + if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { + r.updateStatusError(ctx, dialer, err) + return ctrl.Result{}, err + } else { + err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) + return ctrl.Result{}, err + } + } else if err != nil { + r.updateStatusError(ctx, dialer, err) + return ctrl.Result{}, err + } } return ctrl.Result{}, nil @@ -199,6 +215,16 @@ func (r *PeeringDialerController) updateStatus(ctx context.Context, dialer *cons Error: pointerToBool(false), Message: pointerToString(""), } + if peeringVersionString, ok := dialer.Annotations[annotationPeeringVersion]; ok { + peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) + if err != nil { + r.Log.Error(err, "failed to update PeeringDialer status", "name", dialer.Name, "namespace", dialer.Namespace) + return err + } + if dialer.Status.LatestPeeringVersion == nil || *dialer.Status.LatestPeeringVersion < peeringVersion { + dialer.Status.LatestPeeringVersion = pointerToUint64(peeringVersion) + } + } err := r.Status().Update(ctx, dialer) if err != nil { r.Log.Error(err, "failed to update PeeringDialer status", "name", dialer.Name, "namespace", dialer.Namespace) @@ -267,6 +293,19 @@ func (r *PeeringDialerController) deletePeering(ctx context.Context, peerName st return nil } +func (r *PeeringDialerController) versionAnnotationUpdated(dialer *consulv1alpha1.PeeringDialer) (bool, error) { + if peeringVersionString, ok := dialer.Annotations[annotationPeeringVersion]; ok { + peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) + if err != nil { + return false, err + } + if dialer.Status.LatestPeeringVersion == nil || *dialer.Status.LatestPeeringVersion < peeringVersion { + return true, nil + } + } + return false, nil +} + // requestsForPeeringTokens creates a slice of requests for the peering dialer controller. // It enqueues a request for each dialer that needs to be reconciled. It iterates through // the list of dialers and creates a request for the dialer that has the same secret as it's @@ -291,7 +330,7 @@ func (r *PeeringDialerController) requestsForPeeringTokens(object client.Object) return []ctrl.Request{} } -// filterPeeringAcceptors receives meta and object information for Kubernetes resources that are being watched, +// filterPeeringDialers receives meta and object information for Kubernetes resources that are being watched, // which in this case are Secrets. It only returns true if the Secret is a Peering Token Secret. It reads the labels // from the meta of the resource and uses the values of the "consul.hashicorp.com/peering-token" label to validate that // the Secret is a Peering Token Secret. diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index 4715840500..bc530cbdce 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -26,8 +26,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -// TestReconcileCreateUpdatePeeringDialer creates a peering dialer. -func TestReconcileCreateUpdatePeeringDialer(t *testing.T) { +// TestReconcile_CreateUpdatePeeringDialer creates a peering dialer. +func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { t.Parallel() nodeName := "test-node" node2Name := "test-node2" @@ -213,6 +213,58 @@ func TestReconcileCreateUpdatePeeringDialer(t *testing.T) { }, peeringExists: true, }, + "Initiates peering when version annotation is set": { + peeringName: "peering", + k8sObjects: func() []runtime.Object { + dialer := &v1alpha1.PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peering", + Namespace: "default", + Annotations: map[string]string{ + annotationPeeringVersion: "2", + }, + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + }, + }, + Status: v1alpha1.PeeringDialerStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + ResourceVersion: "test-version", + }, + }, + } + return []runtime.Object{dialer} + }, + expectedConsulPeerings: &api.Peering{ + Name: "peering", + State: api.PeeringStateActive, + }, + peeringSecret: func(token string) *corev1.Secret { + return createSecret("dialer-token", "default", "token", token) + }, + expectedStatus: &v1alpha1.PeeringDialerStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + }, + LatestPeeringVersion: pointerToUint64(2), + }, + peeringExists: true, + }, } for name, tt := range cases { t.Run(name, func(t *testing.T) { @@ -327,6 +379,7 @@ func TestReconcileCreateUpdatePeeringDialer(t *testing.T) { require.Equal(t, tt.expectedStatus.SecretRef.Key, dialer.SecretRef().Key) require.Equal(t, tt.expectedStatus.SecretRef.Backend, dialer.SecretRef().Backend) require.Equal(t, "latest-version", dialer.SecretRef().ResourceVersion) + require.Equal(t, tt.expectedStatus.LatestPeeringVersion, dialer.Status.LatestPeeringVersion) require.Contains(t, dialer.Finalizers, FinalizerName) require.NotEmpty(t, dialer.SecretRef().ResourceVersion) require.NotEqual(t, "test-version", dialer.SecretRef().ResourceVersion) @@ -336,6 +389,201 @@ func TestReconcileCreateUpdatePeeringDialer(t *testing.T) { } } +func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { + t.Parallel() + nodeName := "test-node" + node2Name := "test-node2" + cases := map[string]struct { + annotations map[string]string + expErr string + expectedStatus *v1alpha1.PeeringDialerStatus + }{ + "fails if annotation is not a number": { + annotations: map[string]string{ + annotationPeeringVersion: "foo", + }, + expErr: `strconv.ParseUint: parsing "foo": invalid syntax`, + }, + "is no/op if annotation value is less than value in status": { + annotations: map[string]string{ + annotationPeeringVersion: "2", + }, + expectedStatus: &v1alpha1.PeeringDialerStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + }, + LatestPeeringVersion: pointerToUint64(3), + }, + }, + "is no/op if annotation value is equal to value in status": { + annotations: map[string]string{ + annotationPeeringVersion: "3", + }, + expectedStatus: &v1alpha1.PeeringDialerStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + }, + LatestPeeringVersion: pointerToUint64(3), + }, + }, + "updates if annotation value is greater than value in status": { + annotations: map[string]string{ + annotationPeeringVersion: "4", + }, + expectedStatus: &v1alpha1.PeeringDialerStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + }, + LatestPeeringVersion: pointerToUint64(4), + }, + }, + } + for name, tt := range cases { + t.Run(name, func(t *testing.T) { + + // Create test consul server. + acceptorPeerServer, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) { + c.NodeName = nodeName + }) + require.NoError(t, err) + defer acceptorPeerServer.Stop() + acceptorPeerServer.WaitForServiceIntentions(t) + + cfg := &api.Config{ + Address: acceptorPeerServer.HTTPAddr, + } + acceptorClient, err := api.NewClient(cfg) + require.NoError(t, err) + + ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "default"}} + dialer := &v1alpha1.PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peering", + Namespace: "default", + Annotations: tt.annotations, + }, + Spec: v1alpha1.PeeringDialerSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + }, + }, + Status: v1alpha1.PeeringDialerStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "dialer-token", + Key: "token", + Backend: "kubernetes", + }, + ResourceVersion: "latest-version", + }, + LatestPeeringVersion: pointerToUint64(3), + }, + } + // Create fake k8s client + k8sObjects := []runtime.Object{dialer, ns} + + // This is responsible for updating the token generated by the acceptor side with the IP + // of the Consul server as the generated token currently does not have that set on it. + var encodedPeeringToken string + var token struct { + CA string + ServerAddresses []string + ServerName string + PeerID string + } + // Create the initial token. + baseToken, _, err := acceptorClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: "peering"}, nil) + require.NoError(t, err) + // Decode the token to extract the ServerName and PeerID from the token. CA is always NULL. + decodeBytes, err := base64.StdEncoding.DecodeString(baseToken.PeeringToken) + require.NoError(t, err) + err = json.Unmarshal(decodeBytes, &token) + require.NoError(t, err) + // Get the IP of the Consul server. + addr := strings.Split(acceptorPeerServer.HTTPAddr, ":")[0] + // Generate expected token for Peering Initiate. + tokenString := fmt.Sprintf(`{"CA":null,"ServerAddresses":["%s:8300"],"ServerName":"%s","PeerID":"%s"}`, addr, token.ServerName, token.PeerID) + // Create peering initiate secret in Kubernetes. + encodedPeeringToken = base64.StdEncoding.EncodeToString([]byte(tokenString)) + secret := createSecret("dialer-token", "default", "token", encodedPeeringToken) + secret.SetResourceVersion("latest-version") + k8sObjects = append(k8sObjects, secret) + + // Create test consul server. + dialerPeerServer, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) { + c.NodeName = node2Name + }) + require.NoError(t, err) + defer dialerPeerServer.Stop() + dialerPeerServer.WaitForServiceIntentions(t) + + cfg = &api.Config{ + Address: dialerPeerServer.HTTPAddr, + } + dialerClient, err := api.NewClient(cfg) + require.NoError(t, err) + + _, _, err = dialerClient.Peerings().Establish(context.Background(), api.PeeringEstablishRequest{PeerName: "peering", PeeringToken: encodedPeeringToken}, nil) + require.NoError(t, err) + k8sObjects = append(k8sObjects, createSecret("dialer-token-old", "default", "token", "old-token")) + + s := scheme.Scheme + s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringDialer{}, &v1alpha1.PeeringDialerList{}) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(k8sObjects...).Build() + + // Create the peering dialer controller + controller := &PeeringDialerController{ + Client: fakeClient, + Log: logrtest.TestLogger{T: t}, + ConsulClient: dialerClient, + Scheme: s, + } + namespacedName := types.NamespacedName{ + Name: "peering", + Namespace: "default", + } + + resp, err := controller.Reconcile(context.Background(), ctrl.Request{ + NamespacedName: namespacedName, + }) + if tt.expErr != "" { + require.EqualError(t, err, tt.expErr) + } else { + require.NoError(t, err) + require.False(t, resp.Requeue) + + // Get the reconciled PeeringDialer and make assertions on the status + dialer := &v1alpha1.PeeringDialer{} + err = fakeClient.Get(context.Background(), namespacedName, dialer) + require.NoError(t, err) + if tt.expectedStatus != nil { + require.Equal(t, tt.expectedStatus.SecretRef.Name, dialer.SecretRef().Name) + require.Equal(t, tt.expectedStatus.SecretRef.Key, dialer.SecretRef().Key) + require.Equal(t, tt.expectedStatus.SecretRef.Backend, dialer.SecretRef().Backend) + require.Equal(t, "latest-version", dialer.SecretRef().ResourceVersion) + require.Equal(t, tt.expectedStatus.LatestPeeringVersion, dialer.Status.LatestPeeringVersion) + } + } + }) + } +} + // TestSpecStatusSecretsDifferent tests that the correct result is returned // when comparing the secret in the status against the existing secret. func TestSpecStatusSecretsDifferent(t *testing.T) { From 9b7425acd7ec2fceab7707e26580b237e24f5dc3 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 24 Jun 2022 10:24:13 -0400 Subject: [PATCH 008/235] Acceptance Tests for Cluster Peering (#1287) * Add acceptance tests that run connect tests for peering. - Does not support TLS, ACLs and T-Proxy. * Add OSS acceptance test --- .circleci/config.yml | 8 +- acceptance/framework/helpers/helpers.go | 3 +- acceptance/framework/k8s/helpers.go | 14 + .../bases/peering/peering-acceptor.yaml | 10 + .../bases/peering/peering-dialer.yaml | 10 + .../default-namespace/kustomization.yaml | 5 + .../crd-peers/default-namespace/patch.yaml | 10 + .../crd-peers/default/kustomization.yaml | 5 + .../cases/crd-peers/default/patch.yaml | 9 + .../non-default-namespace/kustomization.yaml | 5 + .../non-default-namespace/patch.yaml | 10 + .../default-namespace/kustomization.yaml | 5 + .../default-namespace/patch.yaml | 10 + .../default/kustomization.yaml | 5 + .../static-client-peers/default/patch.yaml | 10 + .../non-default-namespace/kustomization.yaml | 5 + .../non-default-namespace/patch.yaml | 10 + .../partitions/partitions_connect_test.go | 16 +- .../tests/partitions/partitions_sync_test.go | 6 +- acceptance/tests/peering/main_test.go | 22 ++ .../peering_connect_namespaces_test.go | 301 ++++++++++++++++++ .../tests/peering/peering_connect_test.go | 235 ++++++++++++++ charts/consul/values.yaml | 5 +- 23 files changed, 694 insertions(+), 25 deletions(-) create mode 100644 acceptance/tests/fixtures/bases/peering/peering-acceptor.yaml create mode 100644 acceptance/tests/fixtures/bases/peering/peering-dialer.yaml create mode 100644 acceptance/tests/fixtures/cases/crd-peers/default-namespace/kustomization.yaml create mode 100644 acceptance/tests/fixtures/cases/crd-peers/default-namespace/patch.yaml create mode 100644 acceptance/tests/fixtures/cases/crd-peers/default/kustomization.yaml create mode 100644 acceptance/tests/fixtures/cases/crd-peers/default/patch.yaml create mode 100644 acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/kustomization.yaml create mode 100644 acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/patch.yaml create mode 100644 acceptance/tests/fixtures/cases/static-client-peers/default-namespace/kustomization.yaml create mode 100644 acceptance/tests/fixtures/cases/static-client-peers/default-namespace/patch.yaml create mode 100644 acceptance/tests/fixtures/cases/static-client-peers/default/kustomization.yaml create mode 100644 acceptance/tests/fixtures/cases/static-client-peers/default/patch.yaml create mode 100644 acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/kustomization.yaml create mode 100644 acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/patch.yaml create mode 100644 acceptance/tests/peering/main_test.go create mode 100644 acceptance/tests/peering/peering_connect_namespaces_test.go create mode 100644 acceptance/tests/peering/peering_connect_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index 04a55b41e0..2b03926070 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -646,7 +646,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies - store_test_results: path: /tmp/test-results @@ -701,7 +701,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" - store_test_results: path: /tmp/test-results @@ -762,7 +762,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" - store_test_results: path: /tmp/test-results @@ -857,7 +857,7 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" - store_test_results: path: /tmp/test-results - store_artifacts: diff --git a/acceptance/framework/helpers/helpers.go b/acceptance/framework/helpers/helpers.go index 17dd805123..2c1a6ebf47 100644 --- a/acceptance/framework/helpers/helpers.go +++ b/acceptance/framework/helpers/helpers.go @@ -12,10 +12,9 @@ import ( "time" "github.com/gruntwork-io/terratest/modules/helm" - "github.com/hashicorp/consul/api" - "github.com/gruntwork-io/terratest/modules/random" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/acceptance/framework/k8s/helpers.go b/acceptance/framework/k8s/helpers.go index 1b895a5e17..3f981336ee 100644 --- a/acceptance/framework/k8s/helpers.go +++ b/acceptance/framework/k8s/helpers.go @@ -125,3 +125,17 @@ func ServiceHost(t *testing.T, cfg *config.TestConfig, ctx environment.TestConte return host } } + +// CopySecret copies a Kubernetes secret from one cluster to another. +func CopySecret(t *testing.T, sourceContext, destContext environment.TestContext, secretName string) { + t.Helper() + var secret *corev1.Secret + var err error + retry.Run(t, func(r *retry.R) { + secret, err = sourceContext.KubernetesClient(t).CoreV1().Secrets(sourceContext.KubectlOptions(t).Namespace).Get(context.Background(), secretName, metav1.GetOptions{}) + secret.ResourceVersion = "" + require.NoError(r, err) + }) + _, err = destContext.KubernetesClient(t).CoreV1().Secrets(destContext.KubectlOptions(t).Namespace).Create(context.Background(), secret, metav1.CreateOptions{}) + require.NoError(t, err) +} diff --git a/acceptance/tests/fixtures/bases/peering/peering-acceptor.yaml b/acceptance/tests/fixtures/bases/peering/peering-acceptor.yaml new file mode 100644 index 0000000000..3eff952833 --- /dev/null +++ b/acceptance/tests/fixtures/bases/peering/peering-acceptor.yaml @@ -0,0 +1,10 @@ +apiVersion: consul.hashicorp.com/v1alpha1 +kind: PeeringAcceptor +metadata: + name: server +spec: + peer: + secret: + name: "api-token" + key: "data" + backend: "kubernetes" \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/peering/peering-dialer.yaml b/acceptance/tests/fixtures/bases/peering/peering-dialer.yaml new file mode 100644 index 0000000000..ec125d7bb6 --- /dev/null +++ b/acceptance/tests/fixtures/bases/peering/peering-dialer.yaml @@ -0,0 +1,10 @@ +apiVersion: consul.hashicorp.com/v1alpha1 +kind: PeeringDialer +metadata: + name: client +spec: + peer: + secret: + name: "api-token" + key: "data" + backend: "kubernetes" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/crd-peers/default-namespace/kustomization.yaml b/acceptance/tests/fixtures/cases/crd-peers/default-namespace/kustomization.yaml new file mode 100644 index 0000000000..499fdc5bc1 --- /dev/null +++ b/acceptance/tests/fixtures/cases/crd-peers/default-namespace/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - ../../../bases/exportedservices-default + +patchesStrategicMerge: +- patch.yaml diff --git a/acceptance/tests/fixtures/cases/crd-peers/default-namespace/patch.yaml b/acceptance/tests/fixtures/cases/crd-peers/default-namespace/patch.yaml new file mode 100644 index 0000000000..eed6bee4cc --- /dev/null +++ b/acceptance/tests/fixtures/cases/crd-peers/default-namespace/patch.yaml @@ -0,0 +1,10 @@ +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ExportedServices +metadata: + name: default +spec: + services: + - name: static-server + namespace: default + consumers: + - peer: client diff --git a/acceptance/tests/fixtures/cases/crd-peers/default/kustomization.yaml b/acceptance/tests/fixtures/cases/crd-peers/default/kustomization.yaml new file mode 100644 index 0000000000..499fdc5bc1 --- /dev/null +++ b/acceptance/tests/fixtures/cases/crd-peers/default/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - ../../../bases/exportedservices-default + +patchesStrategicMerge: +- patch.yaml diff --git a/acceptance/tests/fixtures/cases/crd-peers/default/patch.yaml b/acceptance/tests/fixtures/cases/crd-peers/default/patch.yaml new file mode 100644 index 0000000000..b0dcd89ebb --- /dev/null +++ b/acceptance/tests/fixtures/cases/crd-peers/default/patch.yaml @@ -0,0 +1,9 @@ +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ExportedServices +metadata: + name: default +spec: + services: + - name: static-server + consumers: + - peer: client diff --git a/acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/kustomization.yaml b/acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/kustomization.yaml new file mode 100644 index 0000000000..499fdc5bc1 --- /dev/null +++ b/acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - ../../../bases/exportedservices-default + +patchesStrategicMerge: +- patch.yaml diff --git a/acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/patch.yaml b/acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/patch.yaml new file mode 100644 index 0000000000..4162a0f27b --- /dev/null +++ b/acceptance/tests/fixtures/cases/crd-peers/non-default-namespace/patch.yaml @@ -0,0 +1,10 @@ +apiVersion: consul.hashicorp.com/v1alpha1 +kind: ExportedServices +metadata: + name: default +spec: + services: + - name: static-server + namespace: ns1 + consumers: + - peer: client diff --git a/acceptance/tests/fixtures/cases/static-client-peers/default-namespace/kustomization.yaml b/acceptance/tests/fixtures/cases/static-client-peers/default-namespace/kustomization.yaml new file mode 100644 index 0000000000..7191edfb80 --- /dev/null +++ b/acceptance/tests/fixtures/cases/static-client-peers/default-namespace/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - ../../../bases/static-client + +patchesStrategicMerge: + - patch.yaml \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/static-client-peers/default-namespace/patch.yaml b/acceptance/tests/fixtures/cases/static-client-peers/default-namespace/patch.yaml new file mode 100644 index 0000000000..02ea8993ec --- /dev/null +++ b/acceptance/tests/fixtures/cases/static-client-peers/default-namespace/patch.yaml @@ -0,0 +1,10 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: static-client +spec: + template: + metadata: + annotations: + "consul.hashicorp.com/connect-inject": "true" + "consul.hashicorp.com/connect-service-upstreams": "static-server.svc.default.ns.server.peer:1234" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/static-client-peers/default/kustomization.yaml b/acceptance/tests/fixtures/cases/static-client-peers/default/kustomization.yaml new file mode 100644 index 0000000000..7191edfb80 --- /dev/null +++ b/acceptance/tests/fixtures/cases/static-client-peers/default/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - ../../../bases/static-client + +patchesStrategicMerge: + - patch.yaml \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/static-client-peers/default/patch.yaml b/acceptance/tests/fixtures/cases/static-client-peers/default/patch.yaml new file mode 100644 index 0000000000..715485e0f8 --- /dev/null +++ b/acceptance/tests/fixtures/cases/static-client-peers/default/patch.yaml @@ -0,0 +1,10 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: static-client +spec: + template: + metadata: + annotations: + "consul.hashicorp.com/connect-inject": "true" + "consul.hashicorp.com/connect-service-upstreams": "static-server.svc.server.peer:1234" \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/kustomization.yaml b/acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/kustomization.yaml new file mode 100644 index 0000000000..7191edfb80 --- /dev/null +++ b/acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - ../../../bases/static-client + +patchesStrategicMerge: + - patch.yaml \ No newline at end of file diff --git a/acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/patch.yaml b/acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/patch.yaml new file mode 100644 index 0000000000..fd622759a4 --- /dev/null +++ b/acceptance/tests/fixtures/cases/static-client-peers/non-default-namespace/patch.yaml @@ -0,0 +1,10 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: static-client +spec: + template: + metadata: + annotations: + "consul.hashicorp.com/connect-inject": "true" + "consul.hashicorp.com/connect-service-upstreams": "static-server.svc.ns1.ns.server.peer:1234" \ No newline at end of file diff --git a/acceptance/tests/partitions/partitions_connect_test.go b/acceptance/tests/partitions/partitions_connect_test.go index 369da09c26..d57e1af44a 100644 --- a/acceptance/tests/partitions/partitions_connect_test.go +++ b/acceptance/tests/partitions/partitions_connect_test.go @@ -138,19 +138,19 @@ func TestPartitions_Connect(t *testing.T) { caKeySecretName := fmt.Sprintf("%s-consul-ca-key", releaseName) logger.Logf(t, "retrieving ca cert secret %s from the server cluster and applying to the client cluster", caCertSecretName) - copySecret(t, serverClusterContext, clientClusterContext, caCertSecretName) + k8s.CopySecret(t, serverClusterContext, clientClusterContext, caCertSecretName) if !c.ACLsAndAutoEncryptEnabled { // When auto-encrypt is disabled, we need both // the CA cert and CA key to be available in the clients cluster to generate client certificates and keys. logger.Logf(t, "retrieving ca key secret %s from the server cluster and applying to the client cluster", caKeySecretName) - copySecret(t, serverClusterContext, clientClusterContext, caKeySecretName) + k8s.CopySecret(t, serverClusterContext, clientClusterContext, caKeySecretName) } partitionToken := fmt.Sprintf("%s-consul-partitions-acl-token", releaseName) if c.ACLsAndAutoEncryptEnabled { logger.Logf(t, "retrieving partition token secret %s from the server cluster and applying to the client cluster", partitionToken) - copySecret(t, serverClusterContext, clientClusterContext, partitionToken) + k8s.CopySecret(t, serverClusterContext, clientClusterContext, partitionToken) } partitionServiceName := fmt.Sprintf("%s-consul-partition", releaseName) @@ -629,13 +629,3 @@ func TestPartitions_Connect(t *testing.T) { }) } } - -func copySecret(t *testing.T, sourceContext, destContext environment.TestContext, secretName string) { - t.Helper() - - secret, err := sourceContext.KubernetesClient(t).CoreV1().Secrets(sourceContext.KubectlOptions(t).Namespace).Get(context.Background(), secretName, metav1.GetOptions{}) - secret.ResourceVersion = "" - require.NoError(t, err) - _, err = destContext.KubernetesClient(t).CoreV1().Secrets(destContext.KubectlOptions(t).Namespace).Create(context.Background(), secret, metav1.CreateOptions{}) - require.NoError(t, err) -} diff --git a/acceptance/tests/partitions/partitions_sync_test.go b/acceptance/tests/partitions/partitions_sync_test.go index b3f551bd9d..49f265210e 100644 --- a/acceptance/tests/partitions/partitions_sync_test.go +++ b/acceptance/tests/partitions/partitions_sync_test.go @@ -128,19 +128,19 @@ func TestPartitions_Sync(t *testing.T) { caKeySecretName := fmt.Sprintf("%s-consul-ca-key", releaseName) logger.Logf(t, "retrieving ca cert secret %s from the server cluster and applying to the client cluster", caCertSecretName) - copySecret(t, primaryClusterContext, secondaryClusterContext, caCertSecretName) + k8s.CopySecret(t, primaryClusterContext, secondaryClusterContext, caCertSecretName) if !c.ACLsAndAutoEncryptEnabled { // When auto-encrypt is disabled, we need both // the CA cert and CA key to be available in the clients cluster to generate client certificates and keys. logger.Logf(t, "retrieving ca key secret %s from the server cluster and applying to the client cluster", caKeySecretName) - copySecret(t, primaryClusterContext, secondaryClusterContext, caKeySecretName) + k8s.CopySecret(t, primaryClusterContext, secondaryClusterContext, caKeySecretName) } partitionToken := fmt.Sprintf("%s-consul-partitions-acl-token", releaseName) if c.ACLsAndAutoEncryptEnabled { logger.Logf(t, "retrieving partition token secret %s from the server cluster and applying to the client cluster", partitionToken) - copySecret(t, primaryClusterContext, secondaryClusterContext, partitionToken) + k8s.CopySecret(t, primaryClusterContext, secondaryClusterContext, partitionToken) } partitionServiceName := fmt.Sprintf("%s-consul-partition", releaseName) diff --git a/acceptance/tests/peering/main_test.go b/acceptance/tests/peering/main_test.go new file mode 100644 index 0000000000..fff59f1e70 --- /dev/null +++ b/acceptance/tests/peering/main_test.go @@ -0,0 +1,22 @@ +package peering + +import ( + "fmt" + "os" + "testing" + + testsuite "github.com/hashicorp/consul-k8s/acceptance/framework/suite" +) + +var suite testsuite.Suite + +func TestMain(m *testing.M) { + suite = testsuite.NewSuite(m) + + if suite.Config().EnableMultiCluster { + os.Exit(suite.Run()) + } else { + fmt.Println("Skipping peering tests because -enable-multi-cluster is not set") + os.Exit(0) + } +} diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go new file mode 100644 index 0000000000..9388eec360 --- /dev/null +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -0,0 +1,301 @@ +package peering + +import ( + "context" + "strconv" + "testing" + + terratestk8s "github.com/gruntwork-io/terratest/modules/k8s" + "github.com/hashicorp/consul-k8s/acceptance/framework/consul" + "github.com/hashicorp/consul-k8s/acceptance/framework/environment" + "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" + "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" + "github.com/hashicorp/consul-k8s/acceptance/framework/logger" + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const staticClientName = "static-client" +const staticServerName = "static-server" +const staticServerNamespace = "ns1" +const staticClientNamespace = "ns2" + +// Test that Connect works in installations for X-Peers networking. +func TestPeering_ConnectNamespaces(t *testing.T) { + env := suite.Environment() + cfg := suite.Config() + + if !cfg.EnableEnterprise { + t.Skipf("skipping this test because -enable-enterprise is not set") + } + + if cfg.EnableTransparentProxy { + t.Skipf("skipping this test because Transparent Proxy is enabled") + } + + const staticServerPeer = "server" + const staticClientPeer = "client" + const defaultNamespace = "default" + cases := []struct { + name string + destinationNamespace string + mirrorK8S bool + ACLsAndAutoEncryptEnabled bool + }{ + { + "default destination namespace", + defaultNamespace, + false, + false, + }, + { + "single destination namespace", + staticServerNamespace, + false, + false, + }, + { + "mirror k8s namespaces", + staticServerNamespace, + true, + false, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + staticServerPeerClusterContext := env.DefaultContext(t) + staticClientPeerClusterContext := env.Context(t, environment.SecondaryContextName) + + commonHelmValues := map[string]string{ + "global.peering.enabled": "true", + "global.enableConsulNamespaces": "true", + + "global.image": "hashicorp/consul-enterprise:1.13.0-alpha2-ent", + + "global.tls.enabled": "false", + "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), + "global.tls.enableAutoEncrypt": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), + + "global.acls.manageSystemACLs": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), + + "connectInject.enabled": "true", + "connectInject.transparentProxy.defaultEnabled": "false", + // When mirroringK8S is set, this setting is ignored. + "connectInject.consulNamespaces.consulDestinationNamespace": c.destinationNamespace, + "connectInject.consulNamespaces.mirroringK8S": strconv.FormatBool(c.mirrorK8S), + + "meshGateway.enabled": "true", + "meshGateway.replicas": "1", + + "controller.enabled": "true", + } + + staticServerPeerHelmValues := map[string]string{ + "global.datacenter": staticServerPeer, + } + + // On Kind, there are no load balancers but since all clusters + // share the same node network (docker bridge), we can use + // a NodePort service so that we can access node(s) in a different Kind cluster. + if cfg.UseKind { + staticServerPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" + staticServerPeerHelmValues["meshGateway.service.type"] = "NodePort" + staticServerPeerHelmValues["meshGateway.service.nodePort"] = "30100" + } + + releaseName := helpers.RandomName() + + helpers.MergeMaps(staticServerPeerHelmValues, commonHelmValues) + + // Install the first peer where static-server will be deployed in the static-server kubernetes context. + staticServerPeerCluster := consul.NewHelmCluster(t, staticServerPeerHelmValues, staticServerPeerClusterContext, cfg, releaseName) + staticServerPeerCluster.Create(t) + + staticClientPeerHelmValues := map[string]string{ + "global.datacenter": staticClientPeer, + } + + if cfg.UseKind { + staticClientPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" + staticClientPeerHelmValues["meshGateway.service.type"] = "NodePort" + staticClientPeerHelmValues["meshGateway.service.nodePort"] = "30100" + } + + helpers.MergeMaps(staticClientPeerHelmValues, commonHelmValues) + + // Install the second peer where static-client will be deployed in the static-client kubernetes context. + staticClientPeerCluster := consul.NewHelmCluster(t, staticClientPeerHelmValues, staticClientPeerClusterContext, cfg, releaseName) + staticClientPeerCluster.Create(t) + + // Create the peering acceptor on the client peer. + k8s.KubectlApply(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDelete(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") + }) + + // Copy secret from client peer to server peer. + k8s.CopySecret(t, staticClientPeerClusterContext, staticServerPeerClusterContext, "api-token") + + // Create the peering dialer on the server peer. + k8s.KubectlApply(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-dialer.yaml") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.RunKubectl(t, staticServerPeerClusterContext.KubectlOptions(t), "delete", "secret", "api-token") + k8s.KubectlDelete(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-dialer.yaml") + }) + + staticServerOpts := &terratestk8s.KubectlOptions{ + ContextName: staticServerPeerClusterContext.KubectlOptions(t).ContextName, + ConfigPath: staticServerPeerClusterContext.KubectlOptions(t).ConfigPath, + Namespace: staticServerNamespace, + } + staticClientOpts := &terratestk8s.KubectlOptions{ + ContextName: staticClientPeerClusterContext.KubectlOptions(t).ContextName, + ConfigPath: staticClientPeerClusterContext.KubectlOptions(t).ConfigPath, + Namespace: staticClientNamespace, + } + + logger.Logf(t, "creating namespaces %s in server peer", staticServerNamespace) + k8s.RunKubectl(t, staticServerPeerClusterContext.KubectlOptions(t), "create", "ns", staticServerNamespace) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.RunKubectl(t, staticServerPeerClusterContext.KubectlOptions(t), "delete", "ns", staticServerNamespace) + }) + + logger.Logf(t, "creating namespaces %s in client peer", staticClientNamespace) + k8s.RunKubectl(t, staticClientPeerClusterContext.KubectlOptions(t), "create", "ns", staticClientNamespace) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.RunKubectl(t, staticClientPeerClusterContext.KubectlOptions(t), "delete", "ns", staticClientNamespace) + }) + + staticServerPeerClient, _ := staticServerPeerCluster.SetupConsulClient(t, c.ACLsAndAutoEncryptEnabled) + staticClientPeerClient, _ := staticClientPeerCluster.SetupConsulClient(t, c.ACLsAndAutoEncryptEnabled) + + serverQueryOpts := &api.QueryOptions{Namespace: staticServerNamespace} + clientQueryOpts := &api.QueryOptions{Namespace: staticClientNamespace} + + if !c.mirrorK8S { + serverQueryOpts = &api.QueryOptions{Namespace: c.destinationNamespace} + clientQueryOpts = &api.QueryOptions{Namespace: c.destinationNamespace} + } + + // Create a ProxyDefaults resource to configure services to use the mesh + // gateways. + logger.Log(t, "creating proxy-defaults config") + kustomizeDir := "../fixtures/bases/mesh-gateway" + + k8s.KubectlApplyK(t, staticServerPeerClusterContext.KubectlOptions(t), kustomizeDir) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), kustomizeDir) + }) + + k8s.KubectlApplyK(t, staticClientPeerClusterContext.KubectlOptions(t), kustomizeDir) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticClientPeerClusterContext.KubectlOptions(t), kustomizeDir) + }) + + logger.Log(t, "creating static-server in server peer") + k8s.DeployKustomize(t, staticServerOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-server-inject") + + logger.Log(t, "creating static-client deployments in client peer") + if c.destinationNamespace == defaultNamespace { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/default-namespace") + } else { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/non-default-namespace") + } + // Check that both static-server and static-client have been injected and now have 2 containers. + podList, err := staticServerPeerClusterContext.KubernetesClient(t).CoreV1().Pods(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{ + LabelSelector: "app=static-server", + }) + require.NoError(t, err) + require.Len(t, podList.Items, 1) + require.Len(t, podList.Items[0].Spec.Containers, 2) + + podList, err = staticClientPeerClusterContext.KubernetesClient(t).CoreV1().Pods(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{ + LabelSelector: "app=static-client", + }) + require.NoError(t, err) + require.Len(t, podList.Items, 1) + require.Len(t, podList.Items[0].Spec.Containers, 2) + + // Make sure that services are registered in the correct namespace. + // If mirroring is enabled, we expect services to be registered in the + // Consul namespace with the same name as their source + // Kubernetes namespace. + // If a single destination namespace is set, we expect all services + // to be registered in that destination Consul namespace. + // Server cluster. + services, _, err := staticServerPeerClient.Catalog().Service(staticServerName, "", serverQueryOpts) + require.NoError(t, err) + require.Len(t, services, 1) + + // Client cluster. + services, _, err = staticClientPeerClient.Catalog().Service(staticClientName, "", clientQueryOpts) + require.NoError(t, err) + require.Len(t, services, 1) + + logger.Log(t, "creating exported services") + if c.destinationNamespace == defaultNamespace { + k8s.KubectlApplyK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/default-namespace") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/default-namespace") + }) + } else { + k8s.KubectlApplyK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/non-default-namespace") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/non-default-namespace") + }) + } + + logger.Log(t, "checking that connection is successful") + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + + denyAllIntention := &api.ServiceIntentionsConfigEntry{ + Name: "*", + Kind: api.ServiceIntentions, + Namespace: "*", + Sources: []*api.SourceIntention{ + { + Name: "*", + Namespace: "*", + Action: api.IntentionActionDeny, + Peer: staticClientPeer, + }, + }, + } + _, _, err = staticServerPeerClient.ConfigEntries().Set(denyAllIntention, &api.WriteOptions{}) + require.NoError(t, err) + + logger.Log(t, "checking that the connection is not successful because there's no allow intention") + k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + + intention := &api.ServiceIntentionsConfigEntry{ + Name: staticServerName, + Kind: api.ServiceIntentions, + Namespace: staticServerNamespace, + Sources: []*api.SourceIntention{ + { + Name: staticClientName, + Namespace: staticClientNamespace, + Action: api.IntentionActionAllow, + Peer: staticClientPeer, + }, + }, + } + + // Set the destination namespace to be the same + // unless mirrorK8S is true. + if !c.mirrorK8S { + intention.Namespace = c.destinationNamespace + intention.Sources[0].Namespace = c.destinationNamespace + } + + logger.Log(t, "creating intentions in server peer") + _, _, err = staticServerPeerClient.ConfigEntries().Set(intention, &api.WriteOptions{}) + require.NoError(t, err) + + logger.Log(t, "checking that connection is successful") + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + }) + } +} diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go new file mode 100644 index 0000000000..6ef66bdca2 --- /dev/null +++ b/acceptance/tests/peering/peering_connect_test.go @@ -0,0 +1,235 @@ +package peering + +import ( + "context" + "strconv" + "testing" + + terratestk8s "github.com/gruntwork-io/terratest/modules/k8s" + "github.com/hashicorp/consul-k8s/acceptance/framework/consul" + "github.com/hashicorp/consul-k8s/acceptance/framework/environment" + "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" + "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" + "github.com/hashicorp/consul-k8s/acceptance/framework/logger" + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Test that Connect works in installations for X-Peers networking. +func TestPeering_Connect(t *testing.T) { + env := suite.Environment() + cfg := suite.Config() + + if cfg.EnableTransparentProxy { + t.Skipf("skipping this test because Transparent Proxy is enabled") + } + + const staticServerPeer = "server" + const staticClientPeer = "client" + cases := []struct { + name string + ACLsAndAutoEncryptEnabled bool + }{ + { + "default installation", + false, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + staticServerPeerClusterContext := env.DefaultContext(t) + staticClientPeerClusterContext := env.Context(t, environment.SecondaryContextName) + + commonHelmValues := map[string]string{ + "global.peering.enabled": "true", + + "global.image": "hashicorp/consul:1.13.0-alpha2", + + "global.tls.enabled": "false", + "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), + "global.tls.enableAutoEncrypt": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), + + "global.acls.manageSystemACLs": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), + + "connectInject.enabled": "true", + "connectInject.transparentProxy.defaultEnabled": "false", + + "meshGateway.enabled": "true", + "meshGateway.replicas": "1", + + "controller.enabled": "true", + } + + staticServerPeerHelmValues := map[string]string{ + "global.datacenter": staticServerPeer, + } + + // On Kind, there are no load balancers but since all clusters + // share the same node network (docker bridge), we can use + // a NodePort service so that we can access node(s) in a different Kind cluster. + if cfg.UseKind { + staticServerPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" + staticServerPeerHelmValues["meshGateway.service.type"] = "NodePort" + staticServerPeerHelmValues["meshGateway.service.nodePort"] = "30100" + } + + releaseName := helpers.RandomName() + + helpers.MergeMaps(staticServerPeerHelmValues, commonHelmValues) + + // Install the first peer where static-server will be deployed in the static-server kubernetes context. + staticServerPeerCluster := consul.NewHelmCluster(t, staticServerPeerHelmValues, staticServerPeerClusterContext, cfg, releaseName) + staticServerPeerCluster.Create(t) + + staticClientPeerHelmValues := map[string]string{ + "global.datacenter": staticClientPeer, + } + + if cfg.UseKind { + staticClientPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" + staticClientPeerHelmValues["meshGateway.service.type"] = "NodePort" + staticClientPeerHelmValues["meshGateway.service.nodePort"] = "30100" + } + + helpers.MergeMaps(staticClientPeerHelmValues, commonHelmValues) + + // Install the second peer where static-client will be deployed in the static-client kubernetes context. + staticClientPeerCluster := consul.NewHelmCluster(t, staticClientPeerHelmValues, staticClientPeerClusterContext, cfg, releaseName) + staticClientPeerCluster.Create(t) + + // Create the peering acceptor on the client peer. + k8s.KubectlApply(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDelete(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") + }) + + // Copy secret from client peer to server peer. + k8s.CopySecret(t, staticClientPeerClusterContext, staticServerPeerClusterContext, "api-token") + + // Create the peering dialer on the server peer. + k8s.KubectlApply(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-dialer.yaml") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.RunKubectl(t, staticServerPeerClusterContext.KubectlOptions(t), "delete", "secret", "api-token") + k8s.KubectlDelete(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-dialer.yaml") + }) + + staticServerOpts := &terratestk8s.KubectlOptions{ + ContextName: staticServerPeerClusterContext.KubectlOptions(t).ContextName, + ConfigPath: staticServerPeerClusterContext.KubectlOptions(t).ConfigPath, + Namespace: staticServerNamespace, + } + staticClientOpts := &terratestk8s.KubectlOptions{ + ContextName: staticClientPeerClusterContext.KubectlOptions(t).ContextName, + ConfigPath: staticClientPeerClusterContext.KubectlOptions(t).ConfigPath, + Namespace: staticClientNamespace, + } + + logger.Logf(t, "creating namespaces %s in server peer", staticServerNamespace) + k8s.RunKubectl(t, staticServerPeerClusterContext.KubectlOptions(t), "create", "ns", staticServerNamespace) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.RunKubectl(t, staticServerPeerClusterContext.KubectlOptions(t), "delete", "ns", staticServerNamespace) + }) + + logger.Logf(t, "creating namespaces %s in client peer", staticClientNamespace) + k8s.RunKubectl(t, staticClientPeerClusterContext.KubectlOptions(t), "create", "ns", staticClientNamespace) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.RunKubectl(t, staticClientPeerClusterContext.KubectlOptions(t), "delete", "ns", staticClientNamespace) + }) + + staticServerPeerClient, _ := staticServerPeerCluster.SetupConsulClient(t, c.ACLsAndAutoEncryptEnabled) + staticClientPeerClient, _ := staticClientPeerCluster.SetupConsulClient(t, c.ACLsAndAutoEncryptEnabled) + + // Create a ProxyDefaults resource to configure services to use the mesh + // gateways. + logger.Log(t, "creating proxy-defaults config") + kustomizeDir := "../fixtures/bases/mesh-gateway" + + k8s.KubectlApplyK(t, staticServerPeerClusterContext.KubectlOptions(t), kustomizeDir) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), kustomizeDir) + }) + + k8s.KubectlApplyK(t, staticClientPeerClusterContext.KubectlOptions(t), kustomizeDir) + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticClientPeerClusterContext.KubectlOptions(t), kustomizeDir) + }) + + logger.Log(t, "creating static-server in server peer") + k8s.DeployKustomize(t, staticServerOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-server-inject") + + logger.Log(t, "creating static-client deployments in client peer") + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/default") + // Check that both static-server and static-client have been injected and now have 2 containers. + podList, err := staticServerPeerClusterContext.KubernetesClient(t).CoreV1().Pods(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{ + LabelSelector: "app=static-server", + }) + require.NoError(t, err) + require.Len(t, podList.Items, 1) + require.Len(t, podList.Items[0].Spec.Containers, 2) + + podList, err = staticClientPeerClusterContext.KubernetesClient(t).CoreV1().Pods(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{ + LabelSelector: "app=static-client", + }) + require.NoError(t, err) + require.Len(t, podList.Items, 1) + require.Len(t, podList.Items[0].Spec.Containers, 2) + + // Make sure that services are registered in the correct namespace. + // Server cluster. + services, _, err := staticServerPeerClient.Catalog().Service(staticServerName, "", &api.QueryOptions{}) + require.NoError(t, err) + require.Len(t, services, 1) + + // Client cluster. + services, _, err = staticClientPeerClient.Catalog().Service(staticClientName, "", &api.QueryOptions{}) + require.NoError(t, err) + require.Len(t, services, 1) + + logger.Log(t, "creating exported services") + k8s.KubectlApplyK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/default") + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/default") + }) + logger.Log(t, "checking that connection is successful") + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + + denyAllIntention := &api.ServiceIntentionsConfigEntry{ + Name: "*", + Kind: api.ServiceIntentions, + Sources: []*api.SourceIntention{ + { + Name: "*", + Action: api.IntentionActionDeny, + Peer: staticClientPeer, + }, + }, + } + _, _, err = staticServerPeerClient.ConfigEntries().Set(denyAllIntention, &api.WriteOptions{}) + require.NoError(t, err) + + logger.Log(t, "checking that the connection is not successful because there's no allow intention") + k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + + intention := &api.ServiceIntentionsConfigEntry{ + Name: staticServerName, + Kind: api.ServiceIntentions, + Sources: []*api.SourceIntention{ + { + Name: staticClientName, + Action: api.IntentionActionAllow, + Peer: staticClientPeer, + }, + }, + } + + logger.Log(t, "creating intentions in server peer") + _, _, err = staticServerPeerClient.ConfigEntries().Set(intention, &api.WriteOptions{}) + require.NoError(t, err) + + logger.Log(t, "checking that connection is successful") + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + }) + } +} diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 02318c3bc1..0eff7f8734 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -31,9 +31,8 @@ global: # [Experimental] Configures the Cluster Peering feature. Requires Consul v1.13+ and Consul-K8s v0.45+. peering: - # If true, the Helm chart will enable Cluster Peering for the cluster. This will enable peering controllers and - # allow use of the PeeringAcceptor and PeeringDialer CRDs to establish peerings for service mesh. - # @type boolean + # If true, the Helm chart enables Cluster Peering for the cluster. This option enables peering controllers and + # allows use of the PeeringAcceptor and PeeringDialer CRDs for establishing service mesh peerings. enabled: false # [Enterprise Only] Enabling `adminPartitions` allows creation of Admin Partitions in Kubernetes clusters. From d3311e97fce4cedb0e123f2578de093769f99f7a Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Mon, 27 Jun 2022 14:18:34 -0500 Subject: [PATCH 009/235] use anchor link alias for TOC (#1298) * use anchor link alias for TOC in auto-generated helm docs code Co-authored-by: Luke Kysow <1034429+lkysow@users.noreply.github.com> --- .../fixtures/full-values.golden | 52 +++++----- hack/helm-reference-gen/main.go | 10 +- hack/helm-reference-gen/main_test.go | 96 +++++++++---------- 3 files changed, 81 insertions(+), 77 deletions(-) diff --git a/hack/helm-reference-gen/fixtures/full-values.golden b/hack/helm-reference-gen/fixtures/full-values.golden index e29c4d4f5e..b2bbaa4630 100644 --- a/hack/helm-reference-gen/fixtures/full-values.golden +++ b/hack/helm-reference-gen/fixtures/full-values.golden @@ -2,23 +2,23 @@ Use these links to navigate to a particular top-level stanza. -- [`global`](#global) -- [`server`](#server) -- [`externalServers`](#externalservers) -- [`client`](#client) -- [`dns`](#dns) -- [`ui`](#ui) -- [`syncCatalog`](#synccatalog) -- [`connectInject`](#connectinject) -- [`controller`](#controller) -- [`meshGateway`](#meshgateway) -- [`ingressGateways`](#ingressgateways) -- [`terminatingGateways`](#terminatinggateways) -- [`tests`](#tests) +- [`global`](#h-global) +- [`server`](#h-server) +- [`externalServers`](#h-externalservers) +- [`client`](#h-client) +- [`dns`](#h-dns) +- [`ui`](#h-ui) +- [`syncCatalog`](#h-synccatalog) +- [`connectInject`](#h-connectinject) +- [`controller`](#h-controller) +- [`meshGateway`](#h-meshgateway) +- [`ingressGateways`](#h-ingressgateways) +- [`terminatingGateways`](#h-terminatinggateways) +- [`tests`](#h-tests) ## All Values -### global +### global ((#h-global)) - `global` ((#v-global)) - Holds values that affect multiple components of the chart. @@ -245,7 +245,7 @@ Use these links to navigate to a particular top-level stanza. - `enabled` ((#v-global-openshift-enabled)) (`boolean: false`) - If true, the Helm chart will create necessary configuration for running its components on OpenShift. -### server +### server ((#h-server)) - `server` ((#v-server)) - Server, when enabled, configures a server cluster to run. This should be disabled if you plan on connecting to a Consul cluster external to @@ -459,7 +459,7 @@ Use these links to navigate to a particular top-level stanza. feature, in case kubernetes cluster is behind egress http proxies. Additionally, it could be used to configure custom consul parameters. -### externalServers +### externalServers ((#h-externalservers)) - `externalServers` ((#v-externalservers)) - Configuration for Consul servers when the servers are running outside of Kubernetes. When running external servers, configuring these values is recommended @@ -503,7 +503,7 @@ Use these links to navigate to a particular top-level stanza. -o jsonpath="{.clusters[?(@.name=='')].cluster.server}" ``` -### client +### client ((#h-client)) - `client` ((#v-client)) - Values that configure running a Consul client on Kubernetes nodes. @@ -712,7 +712,7 @@ Use these links to navigate to a particular top-level stanza. ... ``` -### dns +### dns ((#h-dns)) - `dns` ((#v-dns)) - Configuration for DNS configuration within the Kubernetes cluster. This creates a service that routes to all agents (client or server) @@ -739,7 +739,7 @@ Use these links to navigate to a particular top-level stanza. This should be a multi-line string mapping directly to a Kubernetes ServiceSpec object. -### ui +### ui ((#h-ui)) - `ui` ((#v-ui)) - Values that configure the Consul UI. @@ -773,7 +773,7 @@ Use these links to navigate to a particular top-level stanza. This should be a multi-line string mapping directly to a Kubernetes ServiceSpec object. -### syncCatalog +### syncCatalog ((#h-synccatalog)) - `syncCatalog` ((#v-synccatalog)) - syncCatalog will run the catalog sync process to sync K8S with Consul services. This can run bidirectional (default) or unidirectionally (Consul @@ -938,7 +938,7 @@ Use these links to navigate to a particular top-level stanza. - `consulWriteInterval` ((#v-synccatalog-consulwriteinterval)) (`string: null`) - Override the default interval to perform syncing operations creating Consul services. -### connectInject +### connectInject ((#h-connectinject)) - `connectInject` ((#v-connectinject)) - ConnectInject will enable the automatic Connect sidecar injector. @@ -1170,7 +1170,7 @@ Use these links to navigate to a particular top-level stanza. - `cpu` ((#v-connectinject-initcontainer-resources-limits-cpu)) (`string: 50m`) -### controller +### controller ((#h-controller)) - `controller` ((#v-controller)) - Controller handles config entry custom resources. Requires consul >= 1.8.4. @@ -1205,7 +1205,7 @@ Use these links to navigate to a particular top-level stanza. - `priorityClassName` ((#v-controller-priorityclassname)) (`string: ""`) - Optional priorityClassName. -### meshGateway +### meshGateway ((#h-meshgateway)) - `meshGateway` ((#v-meshgateway)) - Mesh Gateways enable Consul Connect to work across Consul datacenters. @@ -1354,7 +1354,7 @@ Use these links to navigate to a particular top-level stanza. "annotation-key": "annotation-value" ``` -### ingressGateways +### ingressGateways ((#h-ingressgateways)) - `ingressGateways` ((#v-ingressgateways)) - Configuration options for ingress gateways. Default values for all ingress gateways are defined in `ingressGateways.defaults`. Any of @@ -1460,7 +1460,7 @@ Use these links to navigate to a particular top-level stanza. - `name` ((#v-ingressgateways-gateways-name)) (`string: ingress-gateway`) -### terminatingGateways +### terminatingGateways ((#h-terminatinggateways)) - `terminatingGateways` ((#v-terminatinggateways)) - Configuration options for terminating gateways. Default values for all terminating gateways are defined in `terminatingGateways.defaults`. Any of @@ -1555,7 +1555,7 @@ Use these links to navigate to a particular top-level stanza. - `name` ((#v-terminatinggateways-gateways-name)) (`string: terminating-gateway`) -### tests +### tests ((#h-tests)) - `tests` ((#v-tests)) - Control whether a test Pod manifest is generated when running helm template. When using helm install, the test Pod is not submitted to the cluster so this diff --git a/hack/helm-reference-gen/main.go b/hack/helm-reference-gen/main.go index 9560a281c8..d09c8a8a1c 100644 --- a/hack/helm-reference-gen/main.go +++ b/hack/helm-reference-gen/main.go @@ -54,13 +54,17 @@ var ( // And will not match the "# yaml comment" incorrectly. commentPrefix = regexp.MustCompile(`(?m)^[^\S\n]*#[^\S\n]?`) + funcMap = template.FuncMap{ + "ToLower": strings.ToLower, + } + // docNodeTmpl is the go template used to print a DocNode node. // We use $ instead of ` in the template so we can use the golang raw string // format. We then do the replace from $ => `. docNodeTmpl = template.Must( - template.New("").Parse( + template.New("").Funcs(funcMap).Parse( strings.Replace( - `{{- if eq .Column 1 }}### {{ .Key }} + `{{- if eq .Column 1 }}### {{ .Key }} ((#h-{{ .Key | ToLower }})) {{ end }}{{ .LeadingIndent }}- ${{ .Key }}$ ((#v{{ .HTMLAnchor }})){{ if ne .FormattedKind "" }} (${{ .FormattedKind }}{{ if .FormattedDefault }}: {{ .FormattedDefault }}{{ end }}$){{ end }}{{ if .FormattedDocumentation}} - {{ .FormattedDocumentation }}{{ end }}`, "$", "`", -1)), @@ -407,7 +411,7 @@ func generateTOC(node DocNode) string { toc := tocPrefix for _, c := range node.Children { - toc += fmt.Sprintf("- [`%s`](#%s)\n", c.Key, strings.ToLower(c.Key)) + toc += fmt.Sprintf("- [`%s`](#h-%s)\n", c.Key, strings.ToLower(c.Key)) } return toc + tocSuffix diff --git a/hack/helm-reference-gen/main_test.go b/hack/helm-reference-gen/main_test.go index ed8b00fb90..412d221774 100644 --- a/hack/helm-reference-gen/main_test.go +++ b/hack/helm-reference-gen/main_test.go @@ -20,11 +20,11 @@ func Test(t *testing.T) { # Line 1 # Line 2 key: value`, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($string: value$) - Line 1\n Line 2 `, @@ -34,11 +34,11 @@ key: value`, # Line 1 # Line 2 replicas: 3`, - Exp: `- [$replicas$](#replicas) + Exp: `- [$replicas$](#h-replicas) ## All Values -### replicas +### replicas ((#h-replicas)) - $replicas$ ((#v-replicas)) ($integer: 3$) - Line 1\n Line 2 `, @@ -48,11 +48,11 @@ replicas: 3`, # Line 1 # Line 2 enabled: true`, - Exp: `- [$enabled$](#enabled) + Exp: `- [$enabled$](#h-enabled) ## All Values -### enabled +### enabled ((#h-enabled)) - $enabled$ ((#v-enabled)) ($boolean: true$) - Line 1\n Line 2 `, @@ -65,11 +65,11 @@ map: # Key line 1 # Key line 2 key: value`, - Exp: `- [$map$](#map) + Exp: `- [$map$](#h-map) ## All Values -### map +### map ((#h-map)) - $map$ ((#v-map)) - Map line 1\n Map line 2 @@ -88,11 +88,11 @@ map: int: 1 # Bool docs bool: true`, - Exp: `- [$map$](#map) + Exp: `- [$map$](#h-map) ## All Values -### map +### map ((#h-map)) - $map$ ((#v-map)) - Map line 1\n Map line 2 @@ -109,11 +109,11 @@ map: # key docs # @type: string key: null`, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($string: null$) - key docs `, @@ -124,11 +124,11 @@ key: null`, # # line 2 key: value`, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($string: value$) - line 1\n\n line 2 `, @@ -139,11 +139,11 @@ key: value`, # @type: array serverAdditionalDNSSANs: [] `, - Exp: `- [$serverAdditionalDNSSANs$](#serveradditionaldnssans) + Exp: `- [$serverAdditionalDNSSANs$](#h-serveradditionaldnssans) ## All Values -### serverAdditionalDNSSANs +### serverAdditionalDNSSANs ((#h-serveradditionaldnssans)) - $serverAdditionalDNSSANs$ ((#v-serveradditionaldnssans)) ($array: []$) - line 1 `, @@ -157,11 +157,11 @@ gossipEncryption: # secretKey secretKey: "" `, - Exp: `- [$gossipEncryption$](#gossipencryption) + Exp: `- [$gossipEncryption$](#h-gossipencryption) ## All Values -### gossipEncryption +### gossipEncryption ((#h-gossipencryption)) - $gossipEncryption$ ((#v-gossipencryption)) - gossipEncryption @@ -178,11 +178,11 @@ bootstrapToken: # @type: string secretKey: null `, - Exp: `- [$bootstrapToken$](#bootstraptoken) + Exp: `- [$bootstrapToken$](#h-bootstraptoken) ## All Values -### bootstrapToken +### bootstrapToken ((#h-bootstraptoken)) - $bootstrapToken$ ((#v-bootstraptoken)) @@ -217,11 +217,11 @@ lifecycleSidecarContainer: memory: "50Mi" cpu: "20m" `, - Exp: `- [$lifecycleSidecarContainer$](#lifecyclesidecarcontainer) + Exp: `- [$lifecycleSidecarContainer$](#h-lifecyclesidecarcontainer) ## All Values -### lifecycleSidecarContainer +### lifecycleSidecarContainer ((#h-lifecyclesidecarcontainer)) - $lifecycleSidecarContainer$ ((#v-lifecyclesidecarcontainer)) - lifecycle @@ -263,11 +263,11 @@ server: # @type: boolean enabled: "-" `, - Exp: `- [$server$](#server) + Exp: `- [$server$](#h-server) ## All Values -### server +### server ((#h-server)) - $server$ ((#v-server)) @@ -281,11 +281,11 @@ server: extraConfig: | {} `, - Exp: `- [$extraConfig$](#extraconfig) + Exp: `- [$extraConfig$](#h-extraconfig) ## All Values -### extraConfig +### extraConfig ((#h-extraconfig)) - $extraConfig$ ((#v-extraconfig)) ($string: {}$) `, @@ -303,11 +303,11 @@ affinity: | component: server topologyKey: kubernetes.io/hostname `, - Exp: `- [$affinity$](#affinity) + Exp: `- [$affinity$](#h-affinity) ## All Values -### affinity +### affinity ((#h-affinity)) - $affinity$ ((#v-affinity)) ($string$) - Affinity Settings `, @@ -316,11 +316,11 @@ affinity: | Input: `--- # @type: array k8sAllowNamespaces: ["*"]`, - Exp: `- [$k8sAllowNamespaces$](#k8sallownamespaces) + Exp: `- [$k8sAllowNamespaces$](#h-k8sallownamespaces) ## All Values -### k8sAllowNamespaces +### k8sAllowNamespaces ((#h-k8sallownamespaces)) - $k8sAllowNamespaces$ ((#v-k8sallownamespaces)) ($array: ["*"]$) `, @@ -329,11 +329,11 @@ k8sAllowNamespaces: ["*"]`, Input: `--- # @type: array k8sDenyNamespaces: ["kube-system", "kube-public"]`, - Exp: `- [$k8sDenyNamespaces$](#k8sdenynamespaces) + Exp: `- [$k8sDenyNamespaces$](#h-k8sdenynamespaces) ## All Values -### k8sDenyNamespaces +### k8sDenyNamespaces ((#h-k8sdenynamespaces)) - $k8sDenyNamespaces$ ((#v-k8sdenynamespaces)) ($array: ["kube-system", "kube-public"]$) `, @@ -343,11 +343,11 @@ k8sDenyNamespaces: ["kube-system", "kube-public"]`, # @type: array gateways: - name: ingress-gateway`, - Exp: `- [$gateways$](#gateways) + Exp: `- [$gateways$](#h-gateways) ## All Values -### gateways +### gateways ((#h-gateways)) - $gateways$ ((#v-gateways)) ($array$) @@ -360,11 +360,11 @@ gateways: # line 2 key: value `, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($string: value$) - line 1\n line 2 `, @@ -381,11 +381,11 @@ key: value # $$$ key: value `, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($string: value$) - Examples: @@ -403,11 +403,11 @@ key: value # @type: override-2 key: value `, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($override-2: value$) `, @@ -424,16 +424,16 @@ ports: - port: 8443 nodePort: null `, - Exp: `- [$key$](#key) -- [$ports$](#ports) + Exp: `- [$key$](#h-key) +- [$ports$](#h-ports) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($string: value$) -### ports +### ports ((#h-ports)) - $ports$ ((#v-ports)) ($array$) - port docs `, @@ -443,11 +443,11 @@ ports: # @type: map key: null `, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) ($map$) `, @@ -457,11 +457,11 @@ key: null key: foo: bar `, - Exp: `- [$key$](#key) + Exp: `- [$key$](#h-key) ## All Values -### key +### key ((#h-key)) - $key$ ((#v-key)) From 71884d02d9e31c7534deb98aaf029798e6b11505 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Thu, 23 Jun 2022 09:52:38 -0700 Subject: [PATCH 010/235] Read prometheus TLS config from annotations and pass to bootstrap config --- charts/consul/templates/client-daemonset.yaml | 2 +- .../consul/templates/server-statefulset.yaml | 2 +- control-plane/connect-inject/annotations.go | 6 ++++ .../connect-inject/container_init.go | 30 +++++++++++++++++++ .../connect-inject/container_init_test.go | 8 +++++ 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/charts/consul/templates/client-daemonset.yaml b/charts/consul/templates/client-daemonset.yaml index 33cc400a2f..5632d900f1 100644 --- a/charts/consul/templates/client-daemonset.yaml +++ b/charts/consul/templates/client-daemonset.yaml @@ -1,6 +1,6 @@ {{- if .Values.global.imageK8s }}{{ fail "global.imageK8s is not a valid key, use global.imageK8S (note the capital 'S')" }}{{ end -}} {{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }} -{{- if (and (and .Values.global.tls.enabled .Values.global.tls.httpsOnly) (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics))}}{{ fail "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" }}{{ end -}} +# {{- if (and (and .Values.global.tls.enabled .Values.global.tls.httpsOnly) (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics))}}{{ fail "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" }}{{ end -}} {{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}} {{- if (and .Values.global.adminPartitions.enabled $serverEnabled (ne .Values.global.adminPartitions.name "default"))}}{{ fail "global.adminPartitions.name has to be \"default\" in the server cluster" }}{{ end -}} {{- if (and (not .Values.global.secretsBackend.vault.consulClientRole) .Values.global.secretsBackend.vault.enabled) }}{{ fail "global.secretsBackend.vault.consulClientRole must be provided if global.secretsBackend.vault.enabled=true." }}{{ end -}} diff --git a/charts/consul/templates/server-statefulset.yaml b/charts/consul/templates/server-statefulset.yaml index 56a1904cd9..f0af7f9088 100644 --- a/charts/consul/templates/server-statefulset.yaml +++ b/charts/consul/templates/server-statefulset.yaml @@ -5,7 +5,7 @@ {{- if and .Values.server.serverCert.secretName (not .Values.global.tls.caCert.secretName) }}{{ fail "If server.serverCert.secretName is provided, global.tls.caCert must also be provided" }}{{ end }} {{- if .Values.server.disableFsGroupSecurityContext }}{{ fail "server.disableFsGroupSecurityContext has been removed. Please use global.openshift.enabled instead." }}{{ end }} {{- if .Values.server.bootstrapExpect }}{{ if lt (int .Values.server.bootstrapExpect) (int .Values.server.replicas) }}{{ fail "server.bootstrapExpect cannot be less than server.replicas" }}{{ end }}{{ end }} -{{- if (and (and .Values.global.tls.enabled .Values.global.tls.httpsOnly) (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics))}}{{ fail "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" }}{{ end -}} +# {{- if (and (and .Values.global.tls.enabled .Values.global.tls.httpsOnly) (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics))}}{{ fail "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" }}{{ end -}} {{- if (and .Values.global.gossipEncryption.secretName (not .Values.global.gossipEncryption.secretKey)) }}{{fail "gossipEncryption.secretKey and secretName must both be specified." }}{{ end -}} {{- if (and (not .Values.global.gossipEncryption.secretName) .Values.global.gossipEncryption.secretKey) }}{{fail "gossipEncryption.secretKey and secretName must both be specified." }}{{ end -}} {{- if (and .Values.global.secretsBackend.vault.enabled (not .Values.global.secretsBackend.vault.consulServerRole)) }}{{ fail "global.secretsBackend.vault.consulServerRole must be provided if global.secretsBackend.vault.enabled=true." }}{{ end -}} diff --git a/control-plane/connect-inject/annotations.go b/control-plane/connect-inject/annotations.go index 777eaa1beb..31a4dc7f01 100644 --- a/control-plane/connect-inject/annotations.go +++ b/control-plane/connect-inject/annotations.go @@ -100,6 +100,12 @@ const ( annotationServiceMetricsPort = "consul.hashicorp.com/service-metrics-port" annotationServiceMetricsPath = "consul.hashicorp.com/service-metrics-path" + // annotations for configuring TLS for Prometheus. + annotationPrometheusCAFile = "consul.hashicorp.com/prometheus-ca-file" + annotationPrometheusCAPath = "consul.hashicorp.com/prometheus-ca-path" + annotationPrometheusCertFile = "consul.hashicorp.com/prometheus-cert-file" + annotationPrometheusKeyFile = "consul.hashicorp.com/prometheus-key-file" + // annotationEnvoyExtraArgs is a space-separated list of arguments to be passed to the // envoy binary. See list of args here: https://www.envoyproxy.io/docs/envoy/latest/operations/cli // e.g. consul.hashicorp.com/envoy-extra-args: "--log-level debug --disable-hot-restart" diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index bae4592397..4f12b48c17 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -47,6 +47,11 @@ type initContainerCommandData struct { PrometheusScrapePath string // PrometheusBackendPort configures where the listener on Envoy will point to. PrometheusBackendPort string + // The file paths to use for configuring TLS on the Prometheus metrics endpoint. + PrometheusCAFile string + PrometheusCAPath string + PrometheusCertFile string + PrometheusKeyFile string // EnvoyUID is the Linux user id that will be used when tproxy is enabled. EnvoyUID int @@ -214,6 +219,19 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, data.PrometheusScrapePath = prometheusScrapePath data.PrometheusBackendPort = mergedMetricsPort } + // Pull the TLS config from the relevant annotations. + if raw, ok := pod.Annotations[annotationPrometheusCAFile]; ok && raw != "" { + data.PrometheusCAFile = raw + } + if raw, ok := pod.Annotations[annotationPrometheusCAPath]; ok && raw != "" { + data.PrometheusCAPath = raw + } + if raw, ok := pod.Annotations[annotationPrometheusCertFile]; ok && raw != "" { + data.PrometheusCertFile = raw + } + if raw, ok := pod.Annotations[annotationPrometheusKeyFile]; ok && raw != "" { + data.PrometheusKeyFile = raw + } // Render the command var buf bytes.Buffer @@ -408,6 +426,18 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD {{- if .PrometheusBackendPort }} -prometheus-backend-port="{{ .PrometheusBackendPort }}" \ {{- end }} + {{- if .PrometheusCAFile }} + -prometheus-ca-file="{{ .PrometheusCAFile }}" \ + {{- end }} + {{- if .PrometheusCAPath }} + -prometheus-ca-path="{{ .PrometheusCAPath }}" \ + {{- end }} + {{- if .PrometheusCertFile }} + -prometheus-cert-file="{{ .PrometheusCertFile }}" \ + {{- end }} + {{- if .PrometheusKeyFile }} + -prometheus-key-file="{{ .PrometheusKeyFile }}" \ + {{- end }} {{- if .AuthMethod }} {{- if .MultiPort }} -token-file="/consul/connect-inject/acl-token-{{ .ServiceName }}" \ diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index f97868f603..7f6d6a5ba6 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -116,6 +116,10 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD pod.Annotations[annotationServiceMetricsPort] = "1234" pod.Annotations[annotationPrometheusScrapePort] = "22222" pod.Annotations[annotationPrometheusScrapePath] = "/scrape-path" + pod.Annotations[annotationPrometheusCAFile] = "/certs/ca.crt" + pod.Annotations[annotationPrometheusCAPath] = "/certs/ca/" + pod.Annotations[annotationPrometheusCertFile] = "/certs/server.crt" + pod.Annotations[annotationPrometheusKeyFile] = "/certs/key.pem" return pod }, MeshWebhook{ @@ -126,6 +130,10 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -proxy-id="$(cat /consul/connect-inject/proxyid)" \ -prometheus-scrape-path="/scrape-path" \ -prometheus-backend-port="20100" \ + -prometheus-ca-file="/certs/ca.crt" \ + -prometheus-ca-path="/certs/ca/" \ + -prometheus-cert-file="/certs/server.crt" \ + -prometheus-key-file="/certs/key.pem" \ -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, "", }, From 962fa11b17457427fc9edef7a34efc8fe9944aa7 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Tue, 28 Jun 2022 15:43:51 -0700 Subject: [PATCH 011/235] Add tests for prometheus TLS config validation --- .../connect-inject/container_init.go | 13 ++++ .../connect-inject/container_init_test.go | 70 ++++++++++++++++++- 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index 4f12b48c17..1efcce3cab 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -233,6 +233,19 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, data.PrometheusKeyFile = raw } + // Validate required Prometheus TLS config is present if set. + if data.PrometheusCertFile != "" || data.PrometheusKeyFile != "" || data.PrometheusCAFile != "" || data.PrometheusCAPath != "" { + if data.PrometheusCAFile == "" && data.PrometheusCAPath == "" { + return corev1.Container{}, fmt.Errorf("Must set one of %q or %q when providing prometheus TLS config", annotationPrometheusCAFile, annotationPrometheusCAPath) + } + if data.PrometheusCertFile == "" { + return corev1.Container{}, fmt.Errorf("Must set %q when providing prometheus TLS config", annotationPrometheusCertFile) + } + if data.PrometheusKeyFile == "" { + return corev1.Container{}, fmt.Errorf("Must set %q when providing prometheus TLS config", annotationPrometheusKeyFile) + } + } + // Render the command var buf bytes.Buffer tpl := template.Must(template.New("root").Parse(strings.TrimSpace( diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index 7f6d6a5ba6..7e08756822 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -49,6 +49,7 @@ func TestHandlerContainerInit(t *testing.T) { Webhook MeshWebhook Cmd string // Strings.Contains test CmdNot string // Not contains + ErrStr string // Error contains }{ // The first test checks the whole template. Subsequent tests check // the parts that change. @@ -70,6 +71,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -proxy-id="$(cat /consul/connect-inject/proxyid)" \ -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, "", + "", }, { @@ -99,6 +101,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -service-name="web" \ `, "", + "", }, { "When running the merged metrics server, configures consul connect envoy command", @@ -136,6 +139,67 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -prometheus-key-file="/certs/key.pem" \ -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, "", + "", + }, + { + "When providing Prometheus TLS config, missing CA gives an error", + func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[annotationService] = "web" + pod.Annotations[annotationEnableMetrics] = "true" + pod.Annotations[annotationEnableMetricsMerging] = "true" + pod.Annotations[annotationMergedMetricsPort] = "20100" + pod.Annotations[annotationPrometheusScrapePort] = "22222" + pod.Annotations[annotationPrometheusScrapePath] = "/scrape-path" + pod.Annotations[annotationPrometheusCertFile] = "/certs/server.crt" + pod.Annotations[annotationPrometheusKeyFile] = "/certs/key.pem" + return pod + }, + MeshWebhook{ + ConsulAPITimeout: 5 * time.Second, + }, + "", + "", + fmt.Sprintf("Must set one of %q or %q", annotationPrometheusCAFile, annotationPrometheusCAPath), + }, + { + "When providing Prometheus TLS config, missing cert gives an error", + func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[annotationService] = "web" + pod.Annotations[annotationEnableMetrics] = "true" + pod.Annotations[annotationEnableMetricsMerging] = "true" + pod.Annotations[annotationMergedMetricsPort] = "20100" + pod.Annotations[annotationPrometheusScrapePort] = "22222" + pod.Annotations[annotationPrometheusScrapePath] = "/scrape-path" + pod.Annotations[annotationPrometheusCAFile] = "/certs/ca.crt" + pod.Annotations[annotationPrometheusKeyFile] = "/certs/key.pem" + return pod + }, + MeshWebhook{ + ConsulAPITimeout: 5 * time.Second, + }, + "", + "", + fmt.Sprintf("Must set %q", annotationPrometheusCertFile), + }, + { + "When providing Prometheus TLS config, missing key gives an error", + func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[annotationService] = "web" + pod.Annotations[annotationEnableMetrics] = "true" + pod.Annotations[annotationEnableMetricsMerging] = "true" + pod.Annotations[annotationMergedMetricsPort] = "20100" + pod.Annotations[annotationPrometheusScrapePort] = "22222" + pod.Annotations[annotationPrometheusScrapePath] = "/scrape-path" + pod.Annotations[annotationPrometheusCAPath] = "/certs/ca/" + pod.Annotations[annotationPrometheusCertFile] = "/certs/server.crt" + return pod + }, + MeshWebhook{ + ConsulAPITimeout: 5 * time.Second, + }, + "", + "", + fmt.Sprintf("Must set %q", annotationPrometheusKeyFile), }, } @@ -146,7 +210,11 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD h := tt.Webhook pod := *tt.Pod(minimal()) container, err := h.containerInit(testNS, pod, multiPortInfo{}) - require.NoError(err) + if tt.ErrStr == "" { + require.NoError(err) + } else { + require.Contains(err.Error(), tt.ErrStr) + } actual := strings.Join(container.Command, " ") require.Contains(actual, tt.Cmd) if tt.CmdNot != "" { From 8013a39bf0e392592ee8b4b8460396fe98894782 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Tue, 28 Jun 2022 15:44:54 -0700 Subject: [PATCH 012/235] Remove rule preventing agent metrics and TLS from being set simultaneously --- charts/consul/templates/client-daemonset.yaml | 1 - charts/consul/templates/server-statefulset.yaml | 1 - charts/consul/test/unit/client-daemonset.bats | 14 -------------- charts/consul/test/unit/server-statefulset.bats | 14 -------------- 4 files changed, 30 deletions(-) diff --git a/charts/consul/templates/client-daemonset.yaml b/charts/consul/templates/client-daemonset.yaml index 5632d900f1..0747a1ab68 100644 --- a/charts/consul/templates/client-daemonset.yaml +++ b/charts/consul/templates/client-daemonset.yaml @@ -1,6 +1,5 @@ {{- if .Values.global.imageK8s }}{{ fail "global.imageK8s is not a valid key, use global.imageK8S (note the capital 'S')" }}{{ end -}} {{- if (or (and (ne (.Values.client.enabled | toString) "-") .Values.client.enabled) (and (eq (.Values.client.enabled | toString) "-") .Values.global.enabled)) }} -# {{- if (and (and .Values.global.tls.enabled .Values.global.tls.httpsOnly) (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics))}}{{ fail "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" }}{{ end -}} {{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}} {{- if (and .Values.global.adminPartitions.enabled $serverEnabled (ne .Values.global.adminPartitions.name "default"))}}{{ fail "global.adminPartitions.name has to be \"default\" in the server cluster" }}{{ end -}} {{- if (and (not .Values.global.secretsBackend.vault.consulClientRole) .Values.global.secretsBackend.vault.enabled) }}{{ fail "global.secretsBackend.vault.consulClientRole must be provided if global.secretsBackend.vault.enabled=true." }}{{ end -}} diff --git a/charts/consul/templates/server-statefulset.yaml b/charts/consul/templates/server-statefulset.yaml index f0af7f9088..7caec15b21 100644 --- a/charts/consul/templates/server-statefulset.yaml +++ b/charts/consul/templates/server-statefulset.yaml @@ -5,7 +5,6 @@ {{- if and .Values.server.serverCert.secretName (not .Values.global.tls.caCert.secretName) }}{{ fail "If server.serverCert.secretName is provided, global.tls.caCert must also be provided" }}{{ end }} {{- if .Values.server.disableFsGroupSecurityContext }}{{ fail "server.disableFsGroupSecurityContext has been removed. Please use global.openshift.enabled instead." }}{{ end }} {{- if .Values.server.bootstrapExpect }}{{ if lt (int .Values.server.bootstrapExpect) (int .Values.server.replicas) }}{{ fail "server.bootstrapExpect cannot be less than server.replicas" }}{{ end }}{{ end }} -# {{- if (and (and .Values.global.tls.enabled .Values.global.tls.httpsOnly) (and .Values.global.metrics.enabled .Values.global.metrics.enableAgentMetrics))}}{{ fail "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" }}{{ end -}} {{- if (and .Values.global.gossipEncryption.secretName (not .Values.global.gossipEncryption.secretKey)) }}{{fail "gossipEncryption.secretKey and secretName must both be specified." }}{{ end -}} {{- if (and (not .Values.global.gossipEncryption.secretName) .Values.global.gossipEncryption.secretKey) }}{{fail "gossipEncryption.secretKey and secretName must both be specified." }}{{ end -}} {{- if (and .Values.global.secretsBackend.vault.enabled (not .Values.global.secretsBackend.vault.consulServerRole)) }}{{ fail "global.secretsBackend.vault.consulServerRole must be provided if global.secretsBackend.vault.enabled=true." }}{{ end -}} diff --git a/charts/consul/test/unit/client-daemonset.bats b/charts/consul/test/unit/client-daemonset.bats index 56743ab742..9338e99faf 100755 --- a/charts/consul/test/unit/client-daemonset.bats +++ b/charts/consul/test/unit/client-daemonset.bats @@ -528,20 +528,6 @@ load _helpers [ "${actual}" = "true" ] } -@test "client/DaemonSet: when global.metrics.enableAgentMetrics=true, global.tls.enabled=true and global.tls.httpsOnly=true, fail" { - cd `chart_dir` - run helm template \ - -s templates/client-daemonset.yaml \ - --set 'global.metrics.enabled=true' \ - --set 'global.metrics.enableAgentMetrics=true' \ - --set 'global.tls.enabled=true' \ - --set 'global.tls.httpsOnly=true' \ - . - - [ "$status" -eq 1 ] - [[ "$output" =~ "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" ]] -} - #-------------------------------------------------------------------- # config-configmap diff --git a/charts/consul/test/unit/server-statefulset.bats b/charts/consul/test/unit/server-statefulset.bats index fbac54eca9..5e40fb7d2a 100755 --- a/charts/consul/test/unit/server-statefulset.bats +++ b/charts/consul/test/unit/server-statefulset.bats @@ -648,20 +648,6 @@ load _helpers [ "${actual}" = "/v1/agent/metrics" ] } -@test "server/StatefulSet: when global.metrics.enableAgentMetrics=true, global.tls.enabled=true and global.tls.httpsOnly=true, fail" { - cd `chart_dir` - run helm template \ - -s templates/server-statefulset.yaml \ - --set 'global.metrics.enabled=true' \ - --set 'global.metrics.enableAgentMetrics=true' \ - --set 'global.tls.enabled=true' \ - --set 'global.tls.httpsOnly=true' \ - . - - [ "$status" -eq 1 ] - [[ "$output" =~ "global.metrics.enableAgentMetrics cannot be enabled if TLS (HTTPS only) is enabled" ]] -} - #-------------------------------------------------------------------- # config-configmap From 8407b218377c7e270128302ac9cc0eb39a84bba3 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Tue, 28 Jun 2022 16:57:01 -0700 Subject: [PATCH 013/235] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21c40a9c93..997ba13b5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ FEATURES: * Add support for secret watchers on the Peering Acceptor and Peering Dialer controllers. [[GH-1284](https://github.com/hashicorp/consul-k8s/pull/1284)] * Add support for version annotation on the Peering Acceptor and Peering Dialer controllers. [[GH-1302](https://github.com/hashicorp/consul-k8s/pull/1302)] +IMPROVEMENTS: +* Control Plane + * Added annotations for configuring TLS on Prometheus metrics endpoint for Envoy sidecars. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] + ## 0.45.0 (June 17, 2022) FEATURES: * [Experimental] Cluster Peering: Support Consul cluster peering, which allows service connectivity between two independent clusters. From bb14dc3f818cf942561c0ebcbfa75702d4df4223 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Tue, 28 Jun 2022 19:22:12 -0700 Subject: [PATCH 014/235] Update CHANGELOG.md Co-authored-by: Kyle Schochenmaier --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 997ba13b5f..fb51e1d217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ FEATURES: IMPROVEMENTS: * Control Plane - * Added annotations for configuring TLS on Prometheus metrics endpoint for Envoy sidecars. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] + * Added annotations `consul.hashicorp.com/prometheus-ca-file`, `consul.hashicorp.com/prometheus-ca-path`, `consul.hashicorp.com/prometheus-cert-file`, and `consul.hashicorp.com/prometheus-key-file` for configuring TLS scraping on Prometheus metrics endpoints for Envoy sidecars. To enable, set the cert and key file annotations along with one of the ca file/path annotations. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] ## 0.45.0 (June 17, 2022) FEATURES: From c901d6697d2aad611b8b29d754700d7fd1bdc4eb Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Wed, 29 Jun 2022 11:44:25 -0500 Subject: [PATCH 015/235] fix a broken link (#1311) --- charts/consul/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 0eff7f8734..552082d859 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -756,7 +756,7 @@ server: # The resource requests (CPU, memory, etc.) # for each of the server agents. This should be a YAML map corresponding to a Kubernetes - # ResourceRequirements (https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.11/#resourcerequirements-v1-core) + # ResourceRequirements (https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#resourcerequirements-v1-core) # object. NOTE: The use of a YAML string is deprecated. # # Example: From da13b717493873fc3630ad077e91fa0480e61421 Mon Sep 17 00:00:00 2001 From: Jean Morais Date: Wed, 29 Jun 2022 13:45:17 -0300 Subject: [PATCH 016/235] Add custom annotations support for catalog sync and connectInject pods via Helm (#775) * Add custom annotations support for catalog sync and connectInject pods via Helm --- .../templates/connect-inject-deployment.yaml | 3 +++ .../templates/sync-catalog-deployment.yaml | 3 +++ .../test/unit/connect-inject-deployment.bats | 24 +++++++++++++++++++ .../test/unit/sync-catalog-deployment.bats | 24 +++++++++++++++++++ charts/consul/values.yaml | 24 +++++++++++++++++++ 5 files changed, 78 insertions(+) diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 01622e52ab..134ecbd344 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -40,6 +40,9 @@ spec: component: connect-injector annotations: "consul.hashicorp.com/connect-inject": "false" + {{- if .Values.connectInject.annotations }} + {{- tpl .Values.connectInject.annotations . | nindent 8 }} + {{- end }} {{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }} "vault.hashicorp.com/agent-init-first": "true" "vault.hashicorp.com/agent-inject": "true" diff --git a/charts/consul/templates/sync-catalog-deployment.yaml b/charts/consul/templates/sync-catalog-deployment.yaml index fd9e3ab464..4c8b4359da 100644 --- a/charts/consul/templates/sync-catalog-deployment.yaml +++ b/charts/consul/templates/sync-catalog-deployment.yaml @@ -33,6 +33,9 @@ spec: {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" + {{- if .Values.syncCatalog.annotations }} + {{- tpl .Values.syncCatalog.annotations . | nindent 8 }} + {{- end }} {{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }} "vault.hashicorp.com/agent-init-first": "true" "vault.hashicorp.com/agent-inject": "true" diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 3231a71892..658fca992c 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1692,6 +1692,30 @@ EOF [ "${actual}" = "name" ] } +#-------------------------------------------------------------------- +# annotations + +@test "connectInject/Deployment: no annotations defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.annotations | del(."consul.hashicorp.com/connect-inject")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "connectInject/Deployment: annotations can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.annotations=foo: bar' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.annotations.foo' | tee /dev/stderr) + [ "${actual}" = "bar" ] +} + #-------------------------------------------------------------------- # logLevel diff --git a/charts/consul/test/unit/sync-catalog-deployment.bats b/charts/consul/test/unit/sync-catalog-deployment.bats index 3a65a4c204..0e0ac33a88 100755 --- a/charts/consul/test/unit/sync-catalog-deployment.bats +++ b/charts/consul/test/unit/sync-catalog-deployment.bats @@ -1217,6 +1217,30 @@ load _helpers [ "${actual}" = "bar" ] } +#-------------------------------------------------------------------- +# annotations + +@test "syncCatalog/Deployment: no annotations defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/sync-catalog-deployment.yaml \ + --set 'syncCatalog.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.annotations | del(."consul.hashicorp.com/connect-inject")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "syncCatalog/Deployment: annotations can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/sync-catalog-deployment.yaml \ + --set 'syncCatalog.enabled=true' \ + --set 'syncCatalog.annotations=foo: bar' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.annotations.foo' | tee /dev/stderr) + [ "${actual}" = "bar" ] +} + #-------------------------------------------------------------------- # logLevel diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 552082d859..1c6f77c12f 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -1811,6 +1811,18 @@ syncCatalog: # @type: map extraLabels: null + # This value defines additional annotations for + # the catalog sync pods. This should be formatted as a multi-line string. + # + # ```yaml + # annotations: | + # "sample/annotation1": "foo" + # "sample/annotation2": "bar" + # ``` + # + # @type: string + annotations: null + # Configures the automatic Connect sidecar injector. connectInject: # True if you want to enable connect injection. Set to "-" to inherit from @@ -1894,6 +1906,18 @@ connectInject: # Optional priorityClassName. priorityClassName: "" + # This value defines additional annotations for + # connect inject pods. This should be formatted as a multi-line string. + # + # ```yaml + # annotations: | + # "sample/annotation1": "foo" + # "sample/annotation2": "bar" + # ``` + # + # @type: string + annotations: null + # The Docker image for Consul to use when performing Connect injection. # Defaults to global.image. # @type: string From 0fb689597904dada9a13bb07da406e77d807db3d Mon Sep 17 00:00:00 2001 From: Luke Kysow <1034429+lkysow@users.noreply.github.com> Date: Wed, 29 Jun 2022 11:22:31 -0700 Subject: [PATCH 017/235] changelog for 775 (#1312) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb51e1d217..efd3bb6015 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ FEATURES: IMPROVEMENTS: * Control Plane * Added annotations `consul.hashicorp.com/prometheus-ca-file`, `consul.hashicorp.com/prometheus-ca-path`, `consul.hashicorp.com/prometheus-cert-file`, and `consul.hashicorp.com/prometheus-key-file` for configuring TLS scraping on Prometheus metrics endpoints for Envoy sidecars. To enable, set the cert and key file annotations along with one of the ca file/path annotations. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] +* Helm + * Added `connectInject.annotations` and `syncCatalog.annotations` values for setting annotations on connect inject and sync catalog deployments. [[GH-775](https://github.com/hashicorp/consul-k8s/pull/775)] ## 0.45.0 (June 17, 2022) FEATURES: From e02f2ddbad0cbdefa62df945184647e1b0befdea Mon Sep 17 00:00:00 2001 From: John Murret Date: Wed, 29 Jun 2022 13:06:02 -0600 Subject: [PATCH 018/235] Updating contributing doc to add the correct helm and bats versions (#1314) --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f82fdc6f99..f4ea447aaf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -573,7 +573,7 @@ very quickly. These should be used for fast feedback during development. The acceptance tests require a Kubernetes cluster with a configured `kubectl`. ### Prerequisites -* [Bats](https://github.com/bats-core/bats-core) +* [Bats](https://github.com/bats-core/bats-core) (Currently, must use v1.6.0+.) ```bash brew install bats-core ``` @@ -581,7 +581,7 @@ The acceptance tests require a Kubernetes cluster with a configured `kubectl`. ```bash brew install python-yq ``` -* [Helm 3](https://helm.sh) (Currently, must use v3.6.3. Also, Helm 2 is not supported) +* [Helm 3](https://helm.sh) (Currently, must use v3.8.0+.) ```bash brew install kubernetes-helm ``` From 976f067236350ab882eba656ead90b71b99f825b Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 30 Jun 2022 16:20:42 -0500 Subject: [PATCH 019/235] Add annotations to support specifying userVolumes and userVolumeMounts for the envoy sidecar (#1315) * add envoy user volumes and volumeMounts via annotations --- CHANGELOG.md | 1 + control-plane/connect-inject/annotations.go | 4 + control-plane/connect-inject/envoy_sidecar.go | 11 +++ .../connect-inject/envoy_sidecar_test.go | 63 +++++++++++++ control-plane/connect-inject/mesh_webhook.go | 10 +++ .../connect-inject/mesh_webhook_ent_test.go | 4 +- .../connect-inject/mesh_webhook_test.go | 88 ++++++++++++++++++- 7 files changed, 178 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efd3bb6015..4ed3f02f5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ FEATURES: IMPROVEMENTS: * Control Plane * Added annotations `consul.hashicorp.com/prometheus-ca-file`, `consul.hashicorp.com/prometheus-ca-path`, `consul.hashicorp.com/prometheus-cert-file`, and `consul.hashicorp.com/prometheus-key-file` for configuring TLS scraping on Prometheus metrics endpoints for Envoy sidecars. To enable, set the cert and key file annotations along with one of the ca file/path annotations. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] + * Added annotations `consul.hashicorp.com/consul-sidecar-user-volume` and `consul.hashicorp.com/consul-sidecar-user-volume-mount` for attaching Volumes and VolumeMounts to the Envoy sidecar. Both should be JSON objects. [[GH-1315](https://github.com/hashicorp/consul-k8s/pull/1315)] * Helm * Added `connectInject.annotations` and `syncCatalog.annotations` values for setting annotations on connect inject and sync catalog deployments. [[GH-775](https://github.com/hashicorp/consul-k8s/pull/775)] diff --git a/control-plane/connect-inject/annotations.go b/control-plane/connect-inject/annotations.go index 31a4dc7f01..5c8545ee23 100644 --- a/control-plane/connect-inject/annotations.go +++ b/control-plane/connect-inject/annotations.go @@ -86,6 +86,10 @@ const ( annotationConsulSidecarMemoryLimit = "consul.hashicorp.com/consul-sidecar-memory-limit" annotationConsulSidecarMemoryRequest = "consul.hashicorp.com/consul-sidecar-memory-request" + // annotations for sidecar volumes. + annotationConsulSidecarUserVolume = "consul.hashicorp.com/consul-sidecar-user-volume" + annotationConsulSidecarUserVolumeMount = "consul.hashicorp.com/consul-sidecar-user-volume-mount" + // annotations for sidecar concurrency. annotationEnvoyProxyConcurrency = "consul.hashicorp.com/consul-envoy-proxy-concurrency" diff --git a/control-plane/connect-inject/envoy_sidecar.go b/control-plane/connect-inject/envoy_sidecar.go index 77cc7f47bc..c50fbac5ff 100644 --- a/control-plane/connect-inject/envoy_sidecar.go +++ b/control-plane/connect-inject/envoy_sidecar.go @@ -1,6 +1,7 @@ package connectinject import ( + "encoding/json" "fmt" "strconv" "strings" @@ -48,6 +49,16 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m Command: cmd, } + // Add any extra Envoy VolumeMounts. + if _, ok := pod.Annotations[annotationConsulSidecarUserVolumeMount]; ok { + var volumeMount []corev1.VolumeMount + err := json.Unmarshal([]byte(pod.Annotations[annotationConsulSidecarUserVolumeMount]), &volumeMount) + if err != nil { + return corev1.Container{}, err + } + container.VolumeMounts = append(container.VolumeMounts, volumeMount...) + } + tproxyEnabled, err := transparentProxyEnabled(namespace, pod, w.EnableTransparentProxy) if err != nil { return corev1.Container{}, err diff --git a/control-plane/connect-inject/envoy_sidecar_test.go b/control-plane/connect-inject/envoy_sidecar_test.go index 7727db0fd4..8baa0d30b9 100644 --- a/control-plane/connect-inject/envoy_sidecar_test.go +++ b/control-plane/connect-inject/envoy_sidecar_test.go @@ -394,6 +394,69 @@ func TestHandlerEnvoySidecar_EnvoyExtraArgs(t *testing.T) { } } +func TestHandlerEnvoySidecar_UserVolumeMounts(t *testing.T) { + cases := []struct { + name string + pod corev1.Pod + expectedContainerVolumeMounts []corev1.VolumeMount + expErr string + }{ + { + name: "able to set a sidecar container volume mount via annotation", + pod: corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + annotationEnvoyExtraArgs: "--log-level debug --admin-address-path \"/tmp/consul/foo bar\"", + annotationConsulSidecarUserVolumeMount: "[{\"name\": \"tls-cert\", \"mountPath\": \"/custom/path\"}, {\"name\": \"tls-ca\", \"mountPath\": \"/custom/path2\"}]", + }, + }, + }, + expectedContainerVolumeMounts: []corev1.VolumeMount{ + { + Name: "consul-connect-inject-data", + MountPath: "/consul/connect-inject", + }, + { + Name: "tls-cert", + MountPath: "/custom/path", + }, + { + Name: "tls-ca", + MountPath: "/custom/path2", + }, + }, + }, + { + name: "invalid annotation results in error", + pod: corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + annotationEnvoyExtraArgs: "--log-level debug --admin-address-path \"/tmp/consul/foo bar\"", + annotationConsulSidecarUserVolumeMount: "[abcdefg]", + }, + }, + }, + expErr: "invalid character 'a' looking ", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + h := MeshWebhook{ + ImageConsul: "hashicorp/consul:latest", + ImageEnvoy: "hashicorp/consul-k8s:latest", + } + c, err := h.envoySidecar(testNS, tc.pod, multiPortInfo{}) + if tc.expErr == "" { + require.NoError(t, err) + require.Equal(t, tc.expectedContainerVolumeMounts, c.VolumeMounts) + } else { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expErr) + } + }) + } +} + func TestHandlerEnvoySidecar_Resources(t *testing.T) { mem1 := resource.MustParse("100Mi") mem2 := resource.MustParse("200Mi") diff --git a/control-plane/connect-inject/mesh_webhook.go b/control-plane/connect-inject/mesh_webhook.go index 73b56704fb..cd1e49cd25 100644 --- a/control-plane/connect-inject/mesh_webhook.go +++ b/control-plane/connect-inject/mesh_webhook.go @@ -220,6 +220,16 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi // Optionally mount data volume to other containers w.injectVolumeMount(pod) + // Optionally add any volumes that are to be used by the envoy sidecar. + if _, ok := pod.Annotations[annotationConsulSidecarUserVolume]; ok { + var userVolumes []corev1.Volume + err := json.Unmarshal([]byte(pod.Annotations[annotationConsulSidecarUserVolume]), &userVolumes) + if err != nil { + return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error unmarshalling sidecar user volumes: %s", err)) + } + pod.Spec.Volumes = append(pod.Spec.Volumes, userVolumes...) + } + // Add the upstream services as environment variables for easy // service discovery. containerEnvVars := w.containerEnvVars(pod) diff --git a/control-plane/connect-inject/mesh_webhook_ent_test.go b/control-plane/connect-inject/mesh_webhook_ent_test.go index 5faaf4e0c1..7a34ee3d73 100644 --- a/control-plane/connect-inject/mesh_webhook_ent_test.go +++ b/control-plane/connect-inject/mesh_webhook_ent_test.go @@ -30,7 +30,7 @@ func TestHandler_MutateWithNamespaces(t *testing.T) { basicSpec := corev1.PodSpec{ Containers: []corev1.Container{ - corev1.Container{ + { Name: "web", }, }, @@ -285,7 +285,7 @@ func TestHandler_MutateWithNamespaces(t *testing.T) { func TestHandler_MutateWithNamespaces_ACLs(t *testing.T) { basicSpec := corev1.PodSpec{ Containers: []corev1.Container{ - corev1.Container{ + { Name: "web", }, }, diff --git a/control-plane/connect-inject/mesh_webhook_test.go b/control-plane/connect-inject/mesh_webhook_test.go index bbebd48c30..8b37462506 100644 --- a/control-plane/connect-inject/mesh_webhook_test.go +++ b/control-plane/connect-inject/mesh_webhook_test.go @@ -384,7 +384,93 @@ func TestHandlerHandle(t *testing.T) { }, }, }, - + { + "pod with sidecar volume mount annotation", + MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + Clientset: defaultTestClientWithNamespace(), + }, + admission.Request{ + AdmissionRequest: admissionv1.AdmissionRequest{ + Namespace: namespaces.DefaultNamespace, + Object: encodeRaw(t, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + annotationConsulSidecarUserVolume: "[{\"name\":\"bbb\",\"csi\":{\"driver\":\"bob\"}}]", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "web", + }, + }, + }, + }), + }, + }, + "", + []jsonpatch.Operation{ + { + Operation: "add", + Path: "/spec/volumes", + }, + { + Operation: "add", + Path: "/spec/containers/1", + }, + { + Operation: "add", + Path: "/spec/initContainers", + }, + { + Operation: "add", + Path: "/metadata/annotations/" + escapeJSONPointer(keyInjectStatus), + }, + { + Operation: "add", + Path: "/metadata/annotations/" + escapeJSONPointer(annotationOriginalPod), + }, + { + Operation: "add", + Path: "/metadata/labels", + }, + }, + }, + { + "pod with sidecar invalid volume mount annotation", + MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + Clientset: defaultTestClientWithNamespace(), + }, + admission.Request{ + AdmissionRequest: admissionv1.AdmissionRequest{ + Namespace: namespaces.DefaultNamespace, + Object: encodeRaw(t, &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + annotationConsulSidecarUserVolume: "[a]", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "web", + }, + }, + }, + }), + }, + }, + "error unmarshalling sidecar user volumes: invalid character 'a' looking for beginning of value", + nil, + }, { "pod with service annotation", MeshWebhook{ From 0ed235f2e683ea1b8a922f51a2415cde1a089215 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 30 Jun 2022 16:49:47 -0500 Subject: [PATCH 020/235] use ent images for nightlies and add consul-1.13 nightlies (#1305) * use ent images for nightlies and add support for consul-1.13 * disable nightlies for now --- .circleci/config.yml | 75 ++++++++++++++----- .../peering_connect_namespaces_test.go | 7 ++ .../tests/peering/peering_connect_test.go | 7 ++ 3 files changed, 70 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 2b03926070..8bae0f3ed2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -869,9 +869,9 @@ jobs: acceptance-kind-1-23-consul-nightly-1-11: environment: - TEST_RESULTS: /tmp/test-results - - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul:1.11-dev" - - ENVOY_IMAGE: "envoyproxy/envoy:1.20.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.44.0" + - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.11-dev" + - ENVOY_IMAGE: "envoyproxy/envoy:v1.20.2" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.45.0" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -893,7 +893,7 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11-dev" -envoy-image=$ENVOY_IMAGE + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11" -envoy-image=$ENVOY_IMAGE - store_test_results: path: /tmp/test-results - store_artifacts: @@ -905,9 +905,9 @@ jobs: acceptance-kind-1-23-consul-nightly-1-12: environment: - TEST_RESULTS: /tmp/test-results - - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul:1.12-dev" - - ENVOY_IMAGE: "envoyproxy/envoy:1.22.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.44.0" + - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.12-dev" + - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.45.0" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -929,7 +929,7 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12-dev" -envoy-image=$ENVOY_IMAGE + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12" -envoy-image=$ENVOY_IMAGE - store_test_results: path: /tmp/test-results - store_artifacts: @@ -938,6 +938,42 @@ jobs: fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.12 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-kind-1-23-consul-nightly-1-13: + environment: + - TEST_RESULTS: /tmp/test-results + - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev" + - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.45.0" + machine: + image: ubuntu-2004:202010-01 + resource_class: xlarge + steps: + - checkout + - install-prereqs + - create-kind-clusters: + version: "v1.23.0" + - restore_cache: + keys: + - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + - run: + name: go mod download + working_directory: *acceptance-mod-path + command: go mod download + - save_cache: + key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + paths: + - ~/.go_workspace/pkg/mod + - run: mkdir -p $TEST_RESULTS + - run-acceptance-tests: + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.13" -envoy-image=$ENVOY_IMAGE + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + - slack/status: + fail_only: true + failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.13 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" + workflows: version: 2 test-and-build: @@ -1002,14 +1038,15 @@ workflows: requires: - dev-upload-docker - nightly-acceptance-tests-consul: - triggers: - - schedule: - cron: "0 0 * * *" - filters: - branches: - only: - - main - jobs: - - acceptance-kind-1-23-consul-nightly-1-11 - - acceptance-kind-1-23-consul-nightly-1-12 +# nightly-acceptance-tests-consul: +# triggers: +# - schedule: +# cron: "0 0 * * *" +# filters: +# branches: +# only: +# - main +# jobs: +# - acceptance-kind-1-23-consul-nightly-1-11 +# - acceptance-kind-1-23-consul-nightly-1-12 +# - acceptance-kind-1-23-consul-nightly-1-13 diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index 9388eec360..1ee178dec2 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -2,6 +2,7 @@ package peering import ( "context" + "github.com/hashicorp/go-version" "strconv" "testing" @@ -34,6 +35,12 @@ func TestPeering_ConnectNamespaces(t *testing.T) { t.Skipf("skipping this test because Transparent Proxy is enabled") } + ver, err := version.NewVersion("1.13.0") + require.NoError(t, err) + if cfg.ConsulVersion != nil && cfg.ConsulVersion.LessThan(ver) { + t.Skipf("skipping this test because peering is not supported in version %v", cfg.ConsulVersion.String()) + } + const staticServerPeer = "server" const staticClientPeer = "client" const defaultNamespace = "default" diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index 6ef66bdca2..5b67cc9b40 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -2,6 +2,7 @@ package peering import ( "context" + "github.com/hashicorp/go-version" "strconv" "testing" @@ -25,6 +26,12 @@ func TestPeering_Connect(t *testing.T) { t.Skipf("skipping this test because Transparent Proxy is enabled") } + ver, err := version.NewVersion("1.13.0") + require.NoError(t, err) + if cfg.ConsulVersion != nil && cfg.ConsulVersion.LessThan(ver) { + t.Skipf("skipping this test because peering is not supported in version %v", cfg.ConsulVersion.String()) + } + const staticServerPeer = "server" const staticClientPeer = "client" cases := []struct { From 023007f6b830a08df876557a2cd858120eb46975 Mon Sep 17 00:00:00 2001 From: John Murret Date: Tue, 5 Jul 2022 20:47:08 -0600 Subject: [PATCH 021/235] Updating values docs to only set global.federation.primaryDatacenter outside of the primary datacenter. (#1318) --- charts/consul/values.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 1c6f77c12f..1c756a951d 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -534,7 +534,8 @@ global: # `-consul-federation`. createFederationSecret: false - # The name of the primary datacenter. + # The name of the primary datacenter. This should only be set for datacenters + # that are not the primary datacenter. # @type: string primaryDatacenter: null From faa3ecf08d6a0dc4a6a0e892942c68a7ef451aaf Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Wed, 6 Jul 2022 11:28:14 -0700 Subject: [PATCH 022/235] Peering webhooks (#1310) - adds validation webhooks for PeeringAcceptor and Peering dialer controllers - fixes panic by doing a nil check on the PeeringAcceptor SecretRef() --- CHANGELOG.md | 1 + ...t-inject-mutatingwebhookconfiguration.yaml | 44 +++++ ...t-inject-mutatingwebhookconfiguration.bats | 18 ++ .../api/v1alpha1/peeringacceptor_types.go | 38 +++++ .../v1alpha1/peeringacceptor_types_test.go | 87 ++++++++++ .../api/v1alpha1/peeringacceptor_webhook.go | 69 ++++++++ .../v1alpha1/peeringacceptor_webhook_test.go | 159 ++++++++++++++++++ .../api/v1alpha1/peeringdialer_types.go | 37 ++++ .../api/v1alpha1/peeringdialer_types_test.go | 87 ++++++++++ .../api/v1alpha1/peeringdialer_webhook.go | 67 ++++++++ .../v1alpha1/peeringdialer_webhook_test.go | 159 ++++++++++++++++++ control-plane/config/webhook/manifests.yaml | 42 +++++ .../peering_acceptor_controller.go | 2 +- .../subcommand/inject-connect/command.go | 13 ++ 14 files changed, 822 insertions(+), 1 deletion(-) create mode 100644 control-plane/api/v1alpha1/peeringacceptor_types_test.go create mode 100644 control-plane/api/v1alpha1/peeringacceptor_webhook.go create mode 100644 control-plane/api/v1alpha1/peeringacceptor_webhook_test.go create mode 100644 control-plane/api/v1alpha1/peeringdialer_types_test.go create mode 100644 control-plane/api/v1alpha1/peeringdialer_webhook.go create mode 100644 control-plane/api/v1alpha1/peeringdialer_webhook_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ed3f02f5f..0c915ecd66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ FEATURES: * [Experimental] Cluster Peering: * Add support for secret watchers on the Peering Acceptor and Peering Dialer controllers. [[GH-1284](https://github.com/hashicorp/consul-k8s/pull/1284)] * Add support for version annotation on the Peering Acceptor and Peering Dialer controllers. [[GH-1302](https://github.com/hashicorp/consul-k8s/pull/1302)] + * Add validation webhooks for the Peering Acceptor and Peering Dialer CRDs [[GH-1310](https://github.com/hashicorp/consul-k8s/pull/1310)] IMPROVEMENTS: * Control Plane diff --git a/charts/consul/templates/connect-inject-mutatingwebhookconfiguration.yaml b/charts/consul/templates/connect-inject-mutatingwebhookconfiguration.yaml index c3164bab24..cd5bc8c290 100644 --- a/charts/consul/templates/connect-inject-mutatingwebhookconfiguration.yaml +++ b/charts/consul/templates/connect-inject-mutatingwebhookconfiguration.yaml @@ -38,4 +38,48 @@ webhooks: namespaceSelector: {{ tpl .Values.connectInject.namespaceSelector . | indent 6 }} {{- end }} +{{- if .Values.global.peering.enabled }} + - name: {{ template "consul.fullname" . }}-mutate-peeringacceptors.consul.hashicorp.com + clientConfig: + service: + name: {{ template "consul.fullname" . }}-connect-injector + namespace: {{ .Release.Namespace }} + path: "/mutate-v1alpha1-peeringacceptors" + rules: + - apiGroups: + - consul.hashicorp.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - peeringacceptors + failurePolicy: Fail + sideEffects: None + admissionReviewVersions: + - "v1beta1" + - "v1" + - name: {{ template "consul.fullname" . }}-mutate-peeringdialers.consul.hashicorp.com + clientConfig: + service: + name: {{ template "consul.fullname" . }}-connect-injector + namespace: {{ .Release.Namespace }} + path: "/mutate-v1alpha1-peeringdialers" + rules: + - apiGroups: + - consul.hashicorp.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - peeringdialers + failurePolicy: Fail + sideEffects: None + admissionReviewVersions: + - "v1beta1" + - "v1" +{{- end }} {{- end }} diff --git a/charts/consul/test/unit/connect-inject-mutatingwebhookconfiguration.bats b/charts/consul/test/unit/connect-inject-mutatingwebhookconfiguration.bats index 11c3a6b0a5..6745e690c3 100755 --- a/charts/consul/test/unit/connect-inject-mutatingwebhookconfiguration.bats +++ b/charts/consul/test/unit/connect-inject-mutatingwebhookconfiguration.bats @@ -47,3 +47,21 @@ load _helpers yq '.webhooks[0].clientConfig.service.namespace' | tee /dev/stderr) [ "${actual}" = "\"foo\"" ] } + +@test "connectInject/MutatingWebhookConfiguration: peering is enabled, so webhooks for peering exist" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-mutatingwebhookconfiguration.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.webhooks[1].name | contains("peeringacceptors.consul.hashicorp.com")' | tee /dev/stderr) + [ "${actual}" = "true" ] + local actual=$(helm template \ + -s templates/connect-inject-mutatingwebhookconfiguration.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.webhooks[2].name | contains("peeringdialers.consul.hashicorp.com")' | tee /dev/stderr) + [ "${actual}" = "true" ] +} diff --git a/control-plane/api/v1alpha1/peeringacceptor_types.go b/control-plane/api/v1alpha1/peeringacceptor_types.go index 5dd70b0597..ad671a9e96 100644 --- a/control-plane/api/v1alpha1/peeringacceptor_types.go +++ b/control-plane/api/v1alpha1/peeringacceptor_types.go @@ -1,11 +1,17 @@ package v1alpha1 import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" ) // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. +const PeeringAcceptorKubeKind = "peeringacceptors" +const SecretBackendTypeKubernetes = "kubernetes" + func init() { SchemeBuilder.Register(&PeeringAcceptor{}, &PeeringAcceptorList{}) } @@ -86,3 +92,35 @@ func (pa *PeeringAcceptor) Secret() *Secret { func (pa *PeeringAcceptor) SecretRef() *SecretRefStatus { return pa.Status.SecretRef } +func (pa *PeeringAcceptor) KubeKind() string { + return PeeringAcceptorKubeKind +} +func (pa *PeeringAcceptor) KubernetesName() string { + return pa.ObjectMeta.Name +} +func (pa *PeeringAcceptor) Validate() error { + var errs field.ErrorList + // The nil checks must return since you can't do further validations. + if pa.Spec.Peer == nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("peer"), pa.Spec.Peer, "peer must be specified")) + return apierrors.NewInvalid( + schema.GroupKind{Group: ConsulHashicorpGroup, Kind: PeeringAcceptorKubeKind}, + pa.KubernetesName(), errs) + } + if pa.Spec.Peer.Secret == nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("peer").Child("secret"), pa.Spec.Peer.Secret, "secret must be specified")) + return apierrors.NewInvalid( + schema.GroupKind{Group: ConsulHashicorpGroup, Kind: PeeringAcceptorKubeKind}, + pa.KubernetesName(), errs) + } + // Currently, the only supported backend is "kubernetes". + if pa.Spec.Peer.Secret.Backend != SecretBackendTypeKubernetes { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("peer").Child("secret").Child("backend"), pa.Spec.Peer.Secret.Backend, `backend must be "kubernetes"`)) + } + if len(errs) > 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: ConsulHashicorpGroup, Kind: PeeringAcceptorKubeKind}, + pa.KubernetesName(), errs) + } + return nil +} diff --git a/control-plane/api/v1alpha1/peeringacceptor_types_test.go b/control-plane/api/v1alpha1/peeringacceptor_types_test.go new file mode 100644 index 0000000000..33d437f46a --- /dev/null +++ b/control-plane/api/v1alpha1/peeringacceptor_types_test.go @@ -0,0 +1,87 @@ +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPeeringAcceptor_Validate(t *testing.T) { + cases := map[string]struct { + acceptor *PeeringAcceptor + expectedErrMsgs []string + }{ + "valid": { + acceptor: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "api-token", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + }, + "no peer specified": { + acceptor: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringAcceptorSpec{}, + }, + expectedErrMsgs: []string{ + `spec.peer: Invalid value: "null": peer must be specified`, + }, + }, + "no secret specified": { + acceptor: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{}, + }, + }, + expectedErrMsgs: []string{ + `spec.peer.secret: Invalid value: "null": secret must be specified`, + }, + }, + "invalid secret backend": { + acceptor: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Backend: "invalid", + }, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.peer.secret.backend: Invalid value: "invalid": backend must be "kubernetes"`, + }, + }, + } + + for name, testCase := range cases { + t.Run(name, func(t *testing.T) { + err := testCase.acceptor.Validate() + if len(testCase.expectedErrMsgs) != 0 { + require.Error(t, err) + for _, s := range testCase.expectedErrMsgs { + require.Contains(t, err.Error(), s) + } + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/control-plane/api/v1alpha1/peeringacceptor_webhook.go b/control-plane/api/v1alpha1/peeringacceptor_webhook.go new file mode 100644 index 0000000000..728bd205ee --- /dev/null +++ b/control-plane/api/v1alpha1/peeringacceptor_webhook.go @@ -0,0 +1,69 @@ +package v1alpha1 + +import ( + "context" + "fmt" + "net/http" + + "github.com/go-logr/logr" + capi "github.com/hashicorp/consul/api" + admissionv1 "k8s.io/api/admission/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// +kubebuilder:object:generate=false + +type PeeringAcceptorWebhook struct { + client.Client + ConsulClient *capi.Client + Logger logr.Logger + decoder *admission.Decoder + //ConsulMeta common.ConsulMeta +} + +// NOTE: The path value in the below line is the path to the webhook. +// If it is updated, run code-gen, update subcommand/controller/command.go +// and the consul-helm value for the path to the webhook. +// +// NOTE: The below line cannot be combined with any other comment. If it is +// it will break the code generation. +// +// +kubebuilder:webhook:verbs=create;update,path=/mutate-v1alpha1-peeringacceptors,mutating=true,failurePolicy=fail,groups=consul.hashicorp.com,resources=peeringacceptors,versions=v1alpha1,name=mutate-peeringacceptors.consul.hashicorp.com,sideEffects=None,admissionReviewVersions=v1beta1;v1 + +func (v *PeeringAcceptorWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { + var acceptor PeeringAcceptor + var acceptorList PeeringAcceptorList + err := v.decoder.Decode(req, &acceptor) + if err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + + // Call validate first to ensure all the fields are validated before checking for secret name duplicates. + if err := acceptor.Validate(); err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + + if req.Operation == admissionv1.Create { + v.Logger.Info("validate create", "name", acceptor.KubernetesName()) + + if err := v.Client.List(ctx, &acceptorList); err != nil { + return admission.Errored(http.StatusInternalServerError, err) + } + + for _, item := range acceptorList.Items { + // If any peering acceptor resource has the same secret name as this one, reject it. + if item.Namespace == acceptor.Namespace && item.Secret().Name == acceptor.Secret().Name { + return admission.Errored(http.StatusBadRequest, + fmt.Errorf("an existing PeeringAcceptor resource has the same secret name `name: %s, namespace: %s`", acceptor.Secret().Name, acceptor.Namespace)) + } + } + } + + return admission.Allowed(fmt.Sprintf("valid %s request", acceptor.KubeKind())) +} + +func (v *PeeringAcceptorWebhook) InjectDecoder(d *admission.Decoder) error { + v.decoder = d + return nil +} diff --git a/control-plane/api/v1alpha1/peeringacceptor_webhook_test.go b/control-plane/api/v1alpha1/peeringacceptor_webhook_test.go new file mode 100644 index 0000000000..26ed3e2150 --- /dev/null +++ b/control-plane/api/v1alpha1/peeringacceptor_webhook_test.go @@ -0,0 +1,159 @@ +package v1alpha1 + +import ( + "context" + "encoding/json" + "testing" + + logrtest "github.com/go-logr/logr/testing" + "github.com/stretchr/testify/require" + admissionv1 "k8s.io/api/admission/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +func TestValidatePeeringAcceptor(t *testing.T) { + cases := map[string]struct { + existingResources []runtime.Object + newResource *PeeringAcceptor + expAllow bool + expErrMessage string + }{ + "valid, unique secret name": { + existingResources: []runtime.Object{&PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer1", + Namespace: "default", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }}, + newResource: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer2", + Namespace: "default", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo2", + Key: "data2", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + expAllow: true, + }, + "valid, same secret name, different namespace": { + existingResources: []runtime.Object{&PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer1", + Namespace: "default", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }}, + newResource: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer2", + Namespace: "other", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + expAllow: true, + }, + "invalid, duplicate secret name and namespace": { + existingResources: []runtime.Object{&PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer1", + Namespace: "default", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }}, + newResource: &PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer2", + Namespace: "default", + }, + Spec: PeeringAcceptorSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + expAllow: false, + expErrMessage: "an existing PeeringAcceptor resource has the same secret name `name: foo, namespace: default`", + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + ctx := context.Background() + marshalledRequestObject, err := json.Marshal(c.newResource) + require.NoError(t, err) + s := runtime.NewScheme() + s.AddKnownTypes(GroupVersion, &PeeringAcceptor{}, &PeeringAcceptorList{}) + client := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.existingResources...).Build() + decoder, err := admission.NewDecoder(s) + require.NoError(t, err) + + validator := &PeeringAcceptorWebhook{ + Client: client, + ConsulClient: nil, + Logger: logrtest.TestLogger{T: t}, + decoder: decoder, + } + response := validator.Handle(ctx, admission.Request{ + AdmissionRequest: admissionv1.AdmissionRequest{ + Name: c.newResource.KubernetesName(), + Namespace: "default", + Operation: admissionv1.Create, + Object: runtime.RawExtension{ + Raw: marshalledRequestObject, + }, + }, + }) + + require.Equal(t, c.expAllow, response.Allowed) + if c.expErrMessage != "" { + require.Equal(t, c.expErrMessage, response.AdmissionResponse.Result.Message) + } + }) + } +} diff --git a/control-plane/api/v1alpha1/peeringdialer_types.go b/control-plane/api/v1alpha1/peeringdialer_types.go index 0ffea7bee4..4998b27543 100644 --- a/control-plane/api/v1alpha1/peeringdialer_types.go +++ b/control-plane/api/v1alpha1/peeringdialer_types.go @@ -1,11 +1,16 @@ package v1alpha1 import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" ) // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. +const PeeringDialerKubeKind = "peeringdialers" + func init() { SchemeBuilder.Register(&PeeringDialer{}, &PeeringDialerList{}) } @@ -62,3 +67,35 @@ func (pd *PeeringDialer) Secret() *Secret { func (pd *PeeringDialer) SecretRef() *SecretRefStatus { return pd.Status.SecretRef } +func (pd *PeeringDialer) KubeKind() string { + return PeeringDialerKubeKind +} +func (pd *PeeringDialer) KubernetesName() string { + return pd.ObjectMeta.Name +} +func (pd *PeeringDialer) Validate() error { + var errs field.ErrorList + // The nil checks must return since you can't do further validations. + if pd.Spec.Peer == nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("peer"), pd.Spec.Peer, "peer must be specified")) + return apierrors.NewInvalid( + schema.GroupKind{Group: ConsulHashicorpGroup, Kind: PeeringDialerKubeKind}, + pd.KubernetesName(), errs) + } + if pd.Spec.Peer.Secret == nil { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("peer").Child("secret"), pd.Spec.Peer.Secret, "secret must be specified")) + return apierrors.NewInvalid( + schema.GroupKind{Group: ConsulHashicorpGroup, Kind: PeeringDialerKubeKind}, + pd.KubernetesName(), errs) + } + // Currently, the only supported backend is "kubernetes". + if pd.Spec.Peer.Secret.Backend != "kubernetes" { + errs = append(errs, field.Invalid(field.NewPath("spec").Child("peer").Child("secret").Child("backend"), pd.Spec.Peer.Secret.Backend, `backend must be "kubernetes"`)) + } + if len(errs) > 0 { + return apierrors.NewInvalid( + schema.GroupKind{Group: ConsulHashicorpGroup, Kind: PeeringDialerKubeKind}, + pd.KubernetesName(), errs) + } + return nil +} diff --git a/control-plane/api/v1alpha1/peeringdialer_types_test.go b/control-plane/api/v1alpha1/peeringdialer_types_test.go new file mode 100644 index 0000000000..7e358facb8 --- /dev/null +++ b/control-plane/api/v1alpha1/peeringdialer_types_test.go @@ -0,0 +1,87 @@ +package v1alpha1 + +import ( + "testing" + + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPeeringDialer_Validate(t *testing.T) { + cases := map[string]struct { + dialer *PeeringDialer + expectedErrMsgs []string + }{ + "valid": { + dialer: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "api-token", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + }, + "no peer specified": { + dialer: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringDialerSpec{}, + }, + expectedErrMsgs: []string{ + `spec.peer: Invalid value: "null": peer must be specified`, + }, + }, + "no secret specified": { + dialer: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{}, + }, + }, + expectedErrMsgs: []string{ + `spec.peer.secret: Invalid value: "null": secret must be specified`, + }, + }, + "invalid secret backend": { + dialer: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "api", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Backend: "invalid", + }, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.peer.secret.backend: Invalid value: "invalid": backend must be "kubernetes"`, + }, + }, + } + + for name, testCase := range cases { + t.Run(name, func(t *testing.T) { + err := testCase.dialer.Validate() + if len(testCase.expectedErrMsgs) != 0 { + require.Error(t, err) + for _, s := range testCase.expectedErrMsgs { + require.Contains(t, err.Error(), s) + } + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/control-plane/api/v1alpha1/peeringdialer_webhook.go b/control-plane/api/v1alpha1/peeringdialer_webhook.go new file mode 100644 index 0000000000..587f998155 --- /dev/null +++ b/control-plane/api/v1alpha1/peeringdialer_webhook.go @@ -0,0 +1,67 @@ +package v1alpha1 + +import ( + "context" + "fmt" + "net/http" + + "github.com/go-logr/logr" + capi "github.com/hashicorp/consul/api" + admissionv1 "k8s.io/api/admission/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// +kubebuilder:object:generate=false + +type PeeringDialerWebhook struct { + client.Client + ConsulClient *capi.Client + Logger logr.Logger + decoder *admission.Decoder +} + +// NOTE: The path value in the below line is the path to the webhook. +// If it is updated, run code-gen, update subcommand/controller/command.go +// and the consul-helm value for the path to the webhook. +// +// NOTE: The below line cannot be combined with any other comment. If it is +// it will break the code generation. +// +// +kubebuilder:webhook:verbs=create;update,path=/mutate-v1alpha1-peeringdialers,mutating=true,failurePolicy=fail,groups=consul.hashicorp.com,resources=peeringdialers,versions=v1alpha1,name=mutate-peeringdialers.consul.hashicorp.com,sideEffects=None,admissionReviewVersions=v1beta1;v1 + +func (v *PeeringDialerWebhook) Handle(ctx context.Context, req admission.Request) admission.Response { + var dialer PeeringDialer + var dialerList PeeringDialerList + err := v.decoder.Decode(req, &dialer) + if err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + + // Call validate first to ensure all the fields are validated before checking for secret name duplicates. + if err := dialer.Validate(); err != nil { + return admission.Errored(http.StatusBadRequest, err) + } + + if req.Operation == admissionv1.Create { + v.Logger.Info("validate create", "name", dialer.KubernetesName()) + + if err := v.Client.List(ctx, &dialerList); err != nil { + return admission.Errored(http.StatusInternalServerError, err) + } + + for _, item := range dialerList.Items { + if item.Namespace == dialer.Namespace && item.Secret().Name == dialer.Secret().Name { + return admission.Errored(http.StatusBadRequest, + fmt.Errorf("an existing PeeringDialer resource has the same secret name `name: %s, namespace: %s`", dialer.Secret().Name, dialer.Namespace)) + } + } + } + + return admission.Allowed(fmt.Sprintf("valid %s request", dialer.KubeKind())) +} + +func (v *PeeringDialerWebhook) InjectDecoder(d *admission.Decoder) error { + v.decoder = d + return nil +} diff --git a/control-plane/api/v1alpha1/peeringdialer_webhook_test.go b/control-plane/api/v1alpha1/peeringdialer_webhook_test.go new file mode 100644 index 0000000000..abdca4f417 --- /dev/null +++ b/control-plane/api/v1alpha1/peeringdialer_webhook_test.go @@ -0,0 +1,159 @@ +package v1alpha1 + +import ( + "context" + "encoding/json" + "testing" + + logrtest "github.com/go-logr/logr/testing" + "github.com/stretchr/testify/require" + admissionv1 "k8s.io/api/admission/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +func TestValidatePeeringDialer(t *testing.T) { + cases := map[string]struct { + existingResources []runtime.Object + newResource *PeeringDialer + expAllow bool + expErrMessage string + }{ + "valid, unique secret name": { + existingResources: []runtime.Object{&PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer1", + Namespace: "default", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }}, + newResource: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer2", + Namespace: "default", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo2", + Key: "data2", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + expAllow: true, + }, + "valid, same secret name, different namespace": { + existingResources: []runtime.Object{&PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer1", + Namespace: "default", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }}, + newResource: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer2", + Namespace: "other", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + expAllow: true, + }, + "invalid, duplicate secret name and namespace": { + existingResources: []runtime.Object{&PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer1", + Namespace: "default", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }}, + newResource: &PeeringDialer{ + ObjectMeta: metav1.ObjectMeta{ + Name: "peer2", + Namespace: "default", + }, + Spec: PeeringDialerSpec{ + Peer: &Peer{ + Secret: &Secret{ + Name: "foo", + Key: "data", + Backend: SecretBackendTypeKubernetes, + }, + }, + }, + }, + expAllow: false, + expErrMessage: "an existing PeeringDialer resource has the same secret name `name: foo, namespace: default`", + }, + } + for name, c := range cases { + t.Run(name, func(t *testing.T) { + ctx := context.Background() + marshalledRequestObject, err := json.Marshal(c.newResource) + require.NoError(t, err) + s := runtime.NewScheme() + s.AddKnownTypes(GroupVersion, &PeeringDialer{}, &PeeringDialerList{}) + client := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.existingResources...).Build() + decoder, err := admission.NewDecoder(s) + require.NoError(t, err) + + validator := &PeeringDialerWebhook{ + Client: client, + ConsulClient: nil, + Logger: logrtest.TestLogger{T: t}, + decoder: decoder, + } + response := validator.Handle(ctx, admission.Request{ + AdmissionRequest: admissionv1.AdmissionRequest{ + Name: c.newResource.KubernetesName(), + Namespace: "default", + Operation: admissionv1.Create, + Object: runtime.RawExtension{ + Raw: marshalledRequestObject, + }, + }, + }) + + require.Equal(t, c.expAllow, response.Allowed) + if c.expErrMessage != "" { + require.Equal(t, c.expErrMessage, response.AdmissionResponse.Result.Message) + } + }) + } +} diff --git a/control-plane/config/webhook/manifests.yaml b/control-plane/config/webhook/manifests.yaml index 013ec87f80..c1ffb5e0fe 100644 --- a/control-plane/config/webhook/manifests.yaml +++ b/control-plane/config/webhook/manifests.yaml @@ -68,6 +68,48 @@ webhooks: resources: - mesh sideEffects: None +- admissionReviewVersions: + - v1beta1 + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-v1alpha1-peeringacceptors + failurePolicy: Fail + name: mutate-peeringacceptors.consul.hashicorp.com + rules: + - apiGroups: + - consul.hashicorp.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - peeringacceptors + sideEffects: None +- admissionReviewVersions: + - v1beta1 + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-v1alpha1-peeringdialers + failurePolicy: Fail + name: mutate-peeringdialers.consul.hashicorp.com + rules: + - apiGroups: + - consul.hashicorp.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - peeringdialers + sideEffects: None - admissionReviewVersions: - v1beta1 - v1 diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index 680dc5cc5f..dff8651fd5 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -388,7 +388,7 @@ func (r *PeeringAcceptorController) requestsForPeeringTokens(object client.Objec return []ctrl.Request{} } for _, acceptor := range acceptorList.Items { - if acceptor.SecretRef().Backend == "kubernetes" { + if acceptor.SecretRef() != nil && acceptor.SecretRef().Backend == "kubernetes" { if acceptor.SecretRef().Name == object.GetName() && acceptor.Namespace == object.GetNamespace() { return []ctrl.Request{{NamespacedName: types.NamespacedName{Namespace: acceptor.Namespace, Name: acceptor.Name}}} } diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index 643e5705fd..059bfd6769 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -459,6 +459,19 @@ func (c *Command) Run(args []string) int { setupLog.Error(err, "unable to create controller", "controller", "peering-dialer") return 1 } + + mgr.GetWebhookServer().Register("/mutate-v1alpha1-peeringacceptors", + &webhook.Admission{Handler: &v1alpha1.PeeringAcceptorWebhook{ + Client: mgr.GetClient(), + ConsulClient: c.consulClient, + Logger: ctrl.Log.WithName("webhooks").WithName("peering-acceptor"), + }}) + mgr.GetWebhookServer().Register("/mutate-v1alpha1-peeringdialers", + &webhook.Admission{Handler: &v1alpha1.PeeringDialerWebhook{ + Client: mgr.GetClient(), + ConsulClient: c.consulClient, + Logger: ctrl.Log.WithName("webhooks").WithName("peering-dialer"), + }}) } mgr.GetWebhookServer().CertDir = c.flagCertDir From 47d3415585bca63a71cbc82b7c9579ae0fd4747f Mon Sep 17 00:00:00 2001 From: Erik Berg Date: Wed, 6 Jul 2022 21:03:10 +0200 Subject: [PATCH 023/235] Update client-daemonset bats tests (#1313) * updates client-daemonset bats tests to be more readable and do not use hard-coded array indexes. --- charts/consul/test/unit/client-daemonset.bats | 72 +++++++++---------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/charts/consul/test/unit/client-daemonset.bats b/charts/consul/test/unit/client-daemonset.bats index 9338e99faf..7e3aaa4146 100755 --- a/charts/consul/test/unit/client-daemonset.bats +++ b/charts/consul/test/unit/client-daemonset.bats @@ -1192,7 +1192,7 @@ local actual=$(echo $object | -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=false' \ . | tee /dev/stderr | - yq '[.spec.template.spec.containers[0].env[0].name] | any(contains("CONSUL_HTTP_TOKEN_FILE"))' | tee /dev/stderr) + yq '[.spec.template.spec.containers[] | select(.name == "consul") | .env[] | .name] | any(contains("CONSUL_HTTP_TOKEN_FILE"))' | tee /dev/stderr) [ "${actual}" = "false" ] } @@ -1202,7 +1202,7 @@ local actual=$(echo $object | -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq '[.spec.template.spec.containers[0].env[0].name] | any(contains("CONSUL_HTTP_TOKEN_FILE"))' | tee /dev/stderr) + yq '[.spec.template.spec.containers[] | select(.name == "consul") | .env[] | .name] | any(contains("CONSUL_HTTP_TOKEN_FILE"))' | tee /dev/stderr) [ "${actual}" = "true" ] } @@ -1277,7 +1277,7 @@ local actual=$(echo $object | -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ --set 'global.tls.enabled=true' \ - . | yq '.spec.template.spec.initContainers[0].volumeMounts[2]' | tee /dev/stderr) + . | yq '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .volumeMounts[] | select(.name == "consul-ca-cert")' | tee /dev/stderr) local actual=$(echo $object | yq -r '.name' | tee /dev/stderr) @@ -1298,8 +1298,8 @@ local actual=$(echo $object | -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ --set 'global.tls.enabled=false' \ - . | yq '.spec.template.spec.initContainers[0].volumeMounts[] | select(.name=="consul-ca-cert")' | tee /dev/stderr) - [ "${actual}" == "" ] + . | yq '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .volumeMounts[] | select(.name=="consul-ca-cert")' | tee /dev/stderr) + [ "${object}" == "" ] } @test "client/DaemonSet: fail when externalServers is enabled but the externalServers.hosts is not provided" { @@ -1325,7 +1325,7 @@ local actual=$(echo $object | --set 'externalServers.hosts[0]=foo' \ --set 'externalServers.hosts[1]=bar' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"foo\""))' | tee /dev/stderr) [ "${actual}" = "true" ] @@ -1345,7 +1345,7 @@ local actual=$(echo $object | --set 'externalServers.hosts[0]=computer' \ --set 'externalServers.tlsServerName=foo' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-tls-server-name=foo"))' | tee /dev/stderr) [ "${actual}" = "true" ] @@ -1360,7 +1360,7 @@ local actual=$(echo $object | --set 'server.enabled=false' \ --set 'externalServers.hosts[0]=computer' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-tls-server-name"))' | tee /dev/stderr) [ "${actual}" = "false" ] @@ -1375,7 +1375,7 @@ local actual=$(echo $object | --set 'server.enabled=false' \ --set 'externalServers.hosts[0]=computer' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-use-https"))' | tee /dev/stderr) [ "${actual}" = "false" ] @@ -1391,7 +1391,7 @@ local actual=$(echo $object | --set 'externalServers.hosts[0]=computer' \ --set 'global.tls.enabled=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-use-https"))' | tee /dev/stderr) [ "${actual}" = "true" ] @@ -1407,7 +1407,7 @@ local actual=$(echo $object | --set 'global.tls.enabled=true' \ --set 'externalServers.hosts[0]=computer' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-use-https"))' | tee /dev/stderr) [ "${actual}" = "false" ] @@ -1422,7 +1422,7 @@ local actual=$(echo $object | --set 'server.enabled=false' \ --set 'externalServers.hosts[0]=computer' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-server-port"))' | tee /dev/stderr) [ "${actual}" = "false" ] @@ -1437,7 +1437,7 @@ local actual=$(echo $object | --set 'server.enabled=false' \ --set 'externalServers.hosts[0]=computer' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.initContainers[0].command' | tee /dev/stderr) + yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .command' | tee /dev/stderr) local actual=$(echo $command | jq -r ' . | any(contains("-server-port"))' | tee /dev/stderr) [ "${actual}" = "true" ] @@ -1453,7 +1453,7 @@ local actual=$(echo $object | --set 'client.enabled=true' \ --set 'client.exposeGossipPorts=false' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers | map(select(.name=="consul")) | .[0].env | map(select(.name=="ADVERTISE_IP")) | .[0] | .valueFrom.fieldRef.fieldPath' | + yq -r '.spec.template.spec.containers[] | select(.name=="consul") | .env[] | select(.name=="ADVERTISE_IP") | .valueFrom.fieldRef.fieldPath' | tee /dev/stderr) [ "${actual}" = "status.podIP" ] } @@ -1465,33 +1465,33 @@ local actual=$(echo $object | --set 'client.enabled=true' \ --set 'client.exposeGossipPorts=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers | map(select(.name=="consul")) | .[0].env | map(select(.name=="ADVERTISE_IP")) | .[0] | .valueFrom.fieldRef.fieldPath' | + yq -r '.spec.template.spec.containers[] | select(.name=="consul") | .env[] | select(.name=="ADVERTISE_IP") | .valueFrom.fieldRef.fieldPath' | tee /dev/stderr) [ "${actual}" = "status.hostIP" ] } @test "client/DaemonSet: client doesn't expose hostPorts when client.exposeGossipPorts=false" { cd `chart_dir` - local actual=$(helm template \ + local has_exposed_host_ports=$(helm template \ -s templates/client-daemonset.yaml \ --set 'server.enabled=true' \ --set 'client.enabled=true' \ . | tee /dev/stderr | - yq '.spec.template.spec.containers | map(select(.name=="consul")) | .[0].ports | map(select(.containerPort==8301)) | .[0].hostPort' | + yq '[.spec.template.spec.containers[] | select(.name=="consul") | .ports[] | select(.containerPort==8301)] | any(has("hostPort"))' | tee /dev/stderr) - [ "${actual}" = "null" ] + [ "${has_exposed_host_ports}" = "false" ] } @test "client/DaemonSet: client exposes hostPorts when client.exposeGossipPorts=true" { cd `chart_dir` - local actual=$(helm template \ + local has_exposed_host_ports=$(helm template \ -s templates/client-daemonset.yaml \ --set 'client.enabled=true' \ --set 'client.exposeGossipPorts=true' \ . | tee /dev/stderr | - yq '.spec.template.spec.containers | map(select(.name=="consul")) | .[0].ports | map(select(.containerPort==8301)) | .[0].hostPort' | + yq '[.spec.template.spec.containers[] | select(.name=="consul") | .ports[] | select(.containerPort==8301)] | all(has("hostPort"))' | tee /dev/stderr) - [ "${actual}" = "8301" ] + [ "${has_exposed_host_ports}" = "true" ] } #-------------------------------------------------------------------- @@ -1503,14 +1503,14 @@ local actual=$(echo $object | local actual=$(helm template \ -s templates/client-daemonset.yaml \ . | tee /dev/stderr | - yq '.spec.template.spec.volumes[0].hostPath == null' | tee /dev/stderr ) + yq '.spec.template.spec.volumes[] | select(.name == "data") | .hostPath == null' | tee /dev/stderr ) [ "${actual}" = "true" ] # Test that emptyDir is set instead. local actual=$(helm template \ -s templates/client-daemonset.yaml \ . | tee /dev/stderr | - yq '.spec.template.spec.volumes[0].emptyDir == {}' | tee /dev/stderr ) + yq '.spec.template.spec.volumes[] | select(.name == "data") | .emptyDir == {}' | tee /dev/stderr ) [ "${actual}" = "true" ] } @@ -1520,7 +1520,7 @@ local actual=$(echo $object | -s templates/client-daemonset.yaml \ --set 'client.dataDirectoryHostPath=/opt/consul' \ . | tee /dev/stderr | - yq '.spec.template.spec.volumes[0].hostPath.path == "/opt/consul"' | tee /dev/stderr) + yq '.spec.template.spec.volumes[] | select(.name == "data") | .hostPath.path == "/opt/consul"' | tee /dev/stderr) [ "${actual}" = "true" ] } @@ -1620,12 +1620,12 @@ rollingUpdate: @test "client/DaemonSet: securityContext is not set when global.openshift.enabled=true" { cd `chart_dir` - local actual=$(helm template \ + local has_security_context=$(helm template \ -s templates/client-daemonset.yaml \ --set 'global.openshift.enabled=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.securityContext' | tee /dev/stderr) - [ "${actual}" = "null" ] + yq -r '.spec.template.spec | has("securityContext")' | tee /dev/stderr) + [ "${has_security_context}" = "false" ] } #-------------------------------------------------------------------- @@ -1682,13 +1682,13 @@ rollingUpdate: --set 'client.containerSecurityContext.tlsInit.readOnlyRootFileSystem=true' \ . | tee /dev/stderr) - local actual=$(echo "$manifest" | yq -r '.spec.template.spec.containers | map(select(.name == "consul")) | .[0].securityContext.privileged') + local actual=$(echo "$manifest" | yq -r '.spec.template.spec.containers[] | select(.name == "consul") | .securityContext.privileged') [ "${actual}" = "false" ] - local actual=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers | map(select(.name == "client-acl-init")) | .[0].securityContext.allowPrivilegeEscalation') + local actual=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | .securityContext.allowPrivilegeEscalation') [ "${actual}" = "false" ] - local actual=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers | map(select(.name == "client-tls-init")) | .[0].securityContext.readOnlyRootFileSystem') + local actual=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers[] | select(.name == "client-tls-init") | .securityContext.readOnlyRootFileSystem') [ "${actual}" = "true" ] } @@ -1708,14 +1708,14 @@ rollingUpdate: --set 'client.containerSecurityContext.tlsInit.readOnlyRootFileSystem=true' \ . | tee /dev/stderr) - local actual=$(echo "$manifest" | yq -r '.spec.template.spec.containers | map(select(.name == "consul")) | .[0].securityContext') - [ "${actual}" = "null" ] + local has_security_context=$(echo "$manifest" | yq -r '.spec.template.spec.containers[] | select(.name == "consul") | has("securityContext")') + [ "${has_security_context}" = "false" ] - local actual=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers | map(select(.name == "client-acl-init")) | .[0].securityContext') - [ "${actual}" = "null" ] + local has_security_context=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers[] | select(.name == "client-acl-init") | has("securityContext")') + [ "${has_security_context}" = "false" ] - local actual=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers | map(select(.name == "client-tls-init")) | .[0].securityContext') - [ "${actual}" = "null" ] + local has_security_context=$(echo "$manifest" | yq -r '.spec.template.spec.initContainers[] | select(.name == "client-tls-init") | has("securityContext")') + [ "${has_security_context}" = "false" ] } #-------------------------------------------------------------------- From ca6c2f6e3119aec67998bf662a35cc343b797dc4 Mon Sep 17 00:00:00 2001 From: Erik Berg Date: Thu, 7 Jul 2022 00:14:06 +0200 Subject: [PATCH 024/235] don't set securitycontext on openshift/okd (#1308) If running on OpenShift, these settings cause problems because the user and group ids are below the range openshift expects, instead do not set them. --- .../templates/gossip-encryption-autogenerate-job.yaml | 2 ++ .../test/unit/gossip-encryption-autogenerate-job.bats | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/charts/consul/templates/gossip-encryption-autogenerate-job.yaml b/charts/consul/templates/gossip-encryption-autogenerate-job.yaml index e7c2b52209..e1a6e49823 100644 --- a/charts/consul/templates/gossip-encryption-autogenerate-job.yaml +++ b/charts/consul/templates/gossip-encryption-autogenerate-job.yaml @@ -32,11 +32,13 @@ spec: spec: restartPolicy: Never serviceAccountName: {{ template "consul.fullname" . }}-gossip-encryption-autogenerate + {{- if not .Values.global.openshift.enabled }} securityContext: runAsNonRoot: true runAsGroup: 1000 runAsUser: 100 fsGroup: 1000 + {{- end }} containers: - name: gossip-encryption-autogen image: "{{ .Values.global.imageK8S }}" diff --git a/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats b/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats index 4b5938ab91..87cc5a5990 100644 --- a/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats +++ b/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats @@ -51,3 +51,13 @@ load _helpers [[ "$output" =~ "If global.gossipEncryption.autoGenerate is true, global.gossipEncryption.secretName and global.gossipEncryption.secretKey must not be set." ]] } +@test "gossipEncryptionAutogenerate/Job: securityContext is not set when global.openshift.enabled=true" { + cd `chart_dir` + local has_security_context=$(helm template \ + -s templates/gossip-encryption-autogenerate-job.yaml \ + --set 'global.gossipEncryption.autoGenerate=true' \ + --set 'global.openshift.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec | has("securityContext")' | tee /dev/stderr) + [ "${has_security_context}" = "false" ] +} From 20b969ee3949758caf681af9471e505987a54668 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Wed, 6 Jul 2022 17:43:10 -0500 Subject: [PATCH 025/235] update changelog for community PR 1308 (#1325) * update changelog for community PR * fix indentation --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c915ecd66..6bd8211e63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,10 +9,14 @@ FEATURES: IMPROVEMENTS: * Control Plane * Added annotations `consul.hashicorp.com/prometheus-ca-file`, `consul.hashicorp.com/prometheus-ca-path`, `consul.hashicorp.com/prometheus-cert-file`, and `consul.hashicorp.com/prometheus-key-file` for configuring TLS scraping on Prometheus metrics endpoints for Envoy sidecars. To enable, set the cert and key file annotations along with one of the ca file/path annotations. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] - * Added annotations `consul.hashicorp.com/consul-sidecar-user-volume` and `consul.hashicorp.com/consul-sidecar-user-volume-mount` for attaching Volumes and VolumeMounts to the Envoy sidecar. Both should be JSON objects. [[GH-1315](https://github.com/hashicorp/consul-k8s/pull/1315)] + * Added annotations `consul.hashicorp.com/consul-sidecar-user-volume` and `consul.hashicorp.com/consul-sidecar-user-volume-mount` for attaching Volumes and VolumeMounts to the Envoy sidecar. Both should be JSON objects. [[GH-1315](https://github.com/hashicorp/consul-k8s/pull/1315)] * Helm * Added `connectInject.annotations` and `syncCatalog.annotations` values for setting annotations on connect inject and sync catalog deployments. [[GH-775](https://github.com/hashicorp/consul-k8s/pull/775)] +BUG FIXES: +* Helm + * When using Openshift do not set securityContext in gossip-encryption-autogenerate job. [[GH-1308](https://github.com/hashicorp/consul-k8s/pull/1308)] + ## 0.45.0 (June 17, 2022) FEATURES: * [Experimental] Cluster Peering: Support Consul cluster peering, which allows service connectivity between two independent clusters. From 464521475bec71239159646b505f09e619a27d7d Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Fri, 8 Jul 2022 11:11:19 -0600 Subject: [PATCH 026/235] Fixes for AWS acceptance tests cleanup (#1328) * Fix a bug with ELB deletion where we were comparing pointer values for VPC ID instead of strings * Delete VPCs and their resources even if there's no associated EKS cluster. This so that if EKS cleanup fails in the middle and we re-run it, it will continue deleting resources it couldn't on a previous run. --- hack/aws-acceptance-test-cleanup/main.go | 228 ++++++++++++++--------- 1 file changed, 143 insertions(+), 85 deletions(-) diff --git a/hack/aws-acceptance-test-cleanup/main.go b/hack/aws-acceptance-test-cleanup/main.go index 085d25fee9..e24fd692ce 100644 --- a/hack/aws-acceptance-test-cleanup/main.go +++ b/hack/aws-acceptance-test-cleanup/main.go @@ -66,37 +66,46 @@ func realMain(ctx context.Context) error { ec2Client := ec2.New(clientSession, awsCfg) elbClient := elb.New(clientSession, awsCfg) - // Find clusters to delete. - clusters, err := eksClient.ListClustersWithContext(ctx, &eks.ListClustersInput{}) - if err != nil { - return err - } - var toDeleteClusters []eks.Cluster - for _, cluster := range clusters.Clusters { - if strings.HasPrefix(*cluster, "consul-k8s-") { - // Check the tags of the cluster to ensure they're acceptance test clusters. - clusterData, err := eksClient.DescribeClusterWithContext(ctx, &eks.DescribeClusterInput{ - Name: cluster, - }) - if err != nil { - return err - } - if _, ok := clusterData.Cluster.Tags[buildURLTag]; ok { - toDeleteClusters = append(toDeleteClusters, *clusterData.Cluster) - } - + // Find VPCs to delete. Most resources we create belong to a VPC, except + // for IAM resources, and so if there are no VPCs, that means all leftover resources have been deleted. + var nextToken *string + var toDeleteVPCs []*ec2.Vpc + for { + vpcsOutput, err := ec2Client.DescribeVpcsWithContext(ctx, &ec2.DescribeVpcsInput{ + NextToken: nextToken, + Filters: []*ec2.Filter{ + { + Name: aws.String("tag-key"), + Values: []*string{aws.String(buildURLTag)}, + }, + { + Name: aws.String("tag:Name"), + Values: []*string{aws.String("consul-k8s-*")}, + }, + }, + }) + if err != nil { + return err + } + toDeleteVPCs = append(vpcsOutput.Vpcs) + nextToken = vpcsOutput.NextToken + if nextToken == nil { + break } } - var clusterPrint string - for _, c := range toDeleteClusters { - clusterPrint += fmt.Sprintf("- %s (%s)\n", *c.Name, *c.Tags[buildURLTag]) - } - if len(toDeleteClusters) == 0 { - fmt.Println("No EKS clusters to clean up") + if len(toDeleteVPCs) == 0 { + fmt.Println("Found no VPCs or associated resources to clean up") return nil } - fmt.Printf("Found EKS clusters:\n%s", clusterPrint) + + var vpcPrint string + for _, vpc := range toDeleteVPCs { + vpcName, buildURL := vpcNameAndBuildURL(vpc) + vpcPrint += fmt.Sprintf("- %s (%s)\n", vpcName, buildURL) + } + + fmt.Printf("Found VPCs:\n%s", vpcPrint) // Check for approval. if !flagAutoApprove { @@ -110,7 +119,7 @@ func realMain(ctx context.Context) error { // (see select{} below). go func() { reader := bufio.NewReader(os.Stdin) - fmt.Println("\nDo you want to delete these clusters and associated resources including VPCs (y/n)?") + fmt.Println("\nDo you want to delete these VPCs and associated resources including EKS clusters (y/n)?") inputStr, err := reader.ReadString('\n') if err != nil { inputCh <- input{err: err} @@ -133,77 +142,105 @@ func realMain(ctx context.Context) error { } } - // Delete clusters and associated resources. - for _, cluster := range toDeleteClusters { + // Find EKS clusters to delete. + clusters, err := eksClient.ListClustersWithContext(ctx, &eks.ListClustersInput{}) + if err != nil { + return err + } + toDeleteClusters := make(map[string]eks.Cluster) + for _, cluster := range clusters.Clusters { + if strings.HasPrefix(*cluster, "consul-k8s-") { + // Check the tags of the cluster to ensure they're acceptance test clusters. + clusterData, err := eksClient.DescribeClusterWithContext(ctx, &eks.DescribeClusterInput{ + Name: cluster, + }) + if err != nil { + return err + } + if _, ok := clusterData.Cluster.Tags[buildURLTag]; ok { + toDeleteClusters[*cluster] = *clusterData.Cluster + } - // Delete node groups. - nodeGroups, err := eksClient.ListNodegroupsWithContext(ctx, &eks.ListNodegroupsInput{ - ClusterName: cluster.Name, - }) - if err != nil { - return err } - for _, groupID := range nodeGroups.Nodegroups { - fmt.Printf("Node group: Destroying... [id=%s]\n", *groupID) - _, err = eksClient.DeleteNodegroupWithContext(ctx, &eks.DeleteNodegroupInput{ - ClusterName: cluster.Name, - NodegroupName: groupID, + } + + // Delete VPCs and associated resources. + for _, vpc := range toDeleteVPCs { + fmt.Printf("Deleting VPC and associated resources: %s\n", *vpc.VpcId) + vpcName, _ := vpcNameAndBuildURL(vpc) + cluster, ok := toDeleteClusters[vpcName] + if !ok { + fmt.Printf("Found no associated EKS cluster for VPC: %s\n", vpcName) + } else { + // Delete node groups. + nodeGroups, err := eksClient.ListNodegroupsWithContext(ctx, &eks.ListNodegroupsInput{ + ClusterName: cluster.Name, }) if err != nil { return err } - - // Wait for node group to be deleted. - if err := destroyBackoff(ctx, "Node group", *groupID, func() error { - currNodeGroups, err := eksClient.ListNodegroupsWithContext(ctx, &eks.ListNodegroupsInput{ - ClusterName: cluster.Name, + for _, groupID := range nodeGroups.Nodegroups { + fmt.Printf("Node group: Destroying... [id=%s]\n", *groupID) + _, err = eksClient.DeleteNodegroupWithContext(ctx, &eks.DeleteNodegroupInput{ + ClusterName: cluster.Name, + NodegroupName: groupID, }) if err != nil { return err } - for _, currGroup := range currNodeGroups.Nodegroups { - if *currGroup == *groupID { - return errNotDestroyed + + // Wait for node group to be deleted. + if err := destroyBackoff(ctx, "Node group", *groupID, func() error { + currNodeGroups, err := eksClient.ListNodegroupsWithContext(ctx, &eks.ListNodegroupsInput{ + ClusterName: cluster.Name, + }) + if err != nil { + return err + } + for _, currGroup := range currNodeGroups.Nodegroups { + if *currGroup == *groupID { + return errNotDestroyed + } } + return nil + }); err != nil { + return err } - return nil - }); err != nil { - return err + fmt.Printf("Node group: Destroyed [id=%s]\n", *groupID) } - fmt.Printf("Node group: Destroyed [id=%s]\n", *groupID) - } - // Delete cluster. - fmt.Printf("EKS cluster: Destroying... [id=%s]\n", *cluster.Name) - _, err = eksClient.DeleteClusterWithContext(ctx, &eks.DeleteClusterInput{Name: cluster.Name}) - if err != nil { - return err - } - if err := destroyBackoff(ctx, "EKS cluster", *cluster.Name, func() error { - currClusters, err := eksClient.ListClustersWithContext(ctx, &eks.ListClustersInput{}) + // Delete cluster. + fmt.Printf("EKS cluster: Destroying... [id=%s]\n", *cluster.Name) + _, err = eksClient.DeleteClusterWithContext(ctx, &eks.DeleteClusterInput{Name: cluster.Name}) if err != nil { return err } - for _, currCluster := range currClusters.Clusters { - if *currCluster == *cluster.Name { - return errNotDestroyed + if err := destroyBackoff(ctx, "EKS cluster", *cluster.Name, func() error { + currClusters, err := eksClient.ListClustersWithContext(ctx, &eks.ListClustersInput{}) + if err != nil { + return err + } + for _, currCluster := range currClusters.Clusters { + if *currCluster == *cluster.Name { + return errNotDestroyed + } } + return nil + }); err != nil { + return err } - return nil - }); err != nil { - return err + fmt.Printf("EKS cluster: Destroyed [id=%s]\n", *cluster.Name) } - fmt.Printf("EKS cluster: Destroyed [id=%s]\n", *cluster.Name) - vpcID := cluster.ResourcesVpcConfig.VpcId + vpcID := vpc.VpcId // Once we have the VPC ID, collect VPC peering connections to delete. - filternameAccepter := "accepter-vpc-info.vpc-id" - filternameRequester := "requester-vpc-info.vpc-id" - vpcPeeringConnectionsWithAccepter, err := ec2Client.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ + filterNameAcceptor := "accepter-vpc-info.vpc-id" + filterNameRequester := "requester-vpc-info.vpc-id" + vpcPeeringConnectionsWithAcceptor, err := ec2Client.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ Filters: []*ec2.Filter{ { - Name: &filternameAccepter, + Name: &filterNameAcceptor, Values: []*string{vpcID}, }, }, @@ -215,12 +252,12 @@ func realMain(ctx context.Context) error { vpcPeeringConnectionsWithRequester, err := ec2Client.DescribeVpcPeeringConnections(&ec2.DescribeVpcPeeringConnectionsInput{ Filters: []*ec2.Filter{ { - Name: &filternameRequester, + Name: &filterNameRequester, Values: []*string{vpcID}, }, }, }) - vpcPeeringConnectionsToDelete := append(vpcPeeringConnectionsWithAccepter.VpcPeeringConnections, vpcPeeringConnectionsWithRequester.VpcPeeringConnections...) + vpcPeeringConnectionsToDelete := append(vpcPeeringConnectionsWithAcceptor.VpcPeeringConnections, vpcPeeringConnectionsWithRequester.VpcPeeringConnections...) // Delete NAT gateways. natGateways, err := ec2Client.DescribeNatGatewaysWithContext(ctx, &ec2.DescribeNatGatewaysInput{ @@ -282,7 +319,7 @@ func realMain(ctx context.Context) error { if address.AllocationId != nil { fmt.Printf("NAT gateway: Releasing Elastic IP... [id=%s]\n", *address.AllocationId) _, err := ec2Client.ReleaseAddressWithContext(ctx, &ec2.ReleaseAddressInput{AllocationId: address.AllocationId}) - if err != nil { + if err != nil && !strings.Contains(err.Error(), "InvalidAllocationID.NotFound") { return err } fmt.Printf("NAT gateway: Elastic IP released [id=%s]\n", *address.AllocationId) @@ -296,7 +333,7 @@ func realMain(ctx context.Context) error { return err } for _, elbDescrip := range elbs.LoadBalancerDescriptions { - if elbDescrip.VPCId != vpcID { + if *elbDescrip.VPCId != *vpcID { continue } @@ -313,16 +350,21 @@ func realMain(ctx context.Context) error { currELBs, err := elbClient.DescribeLoadBalancersWithContext(ctx, &elb.DescribeLoadBalancersInput{ LoadBalancerNames: []*string{elbDescrip.LoadBalancerName}, }) - if err != nil { + if strings.Contains(err.Error(), elb.ErrCodeAccessPointNotFoundException) { + return nil + } else if err != nil { return err } if len(currELBs.LoadBalancerDescriptions) > 0 { return errNotDestroyed } + return nil }); err != nil { return err } + // Allow time for ELB deletion to propagate so that we can detach the internet gateway. + time.Sleep(1 * time.Second) fmt.Printf("ELB: Destroyed [id=%s]\n", *elbDescrip.LoadBalancerName) } @@ -419,14 +461,16 @@ func realMain(ctx context.Context) error { }, }) for _, sg := range sgs.SecurityGroups { - revokeSGInput := &ec2.RevokeSecurityGroupIngressInput{GroupId: sg.GroupId} - revokeSGInput.SetIpPermissions(sg.IpPermissions) - fmt.Printf("Security group: Removing security group rules... [id=%s]\n", *sg.GroupId) - _, err := ec2Client.RevokeSecurityGroupIngressWithContext(ctx, revokeSGInput) - if err != nil { - return err + if len(sg.IpPermissions) > 0 { + revokeSGInput := &ec2.RevokeSecurityGroupIngressInput{GroupId: sg.GroupId} + revokeSGInput.SetIpPermissions(sg.IpPermissions) + fmt.Printf("Security group: Removing security group rules... [id=%s]\n", *sg.GroupId) + _, err := ec2Client.RevokeSecurityGroupIngressWithContext(ctx, revokeSGInput) + if err != nil { + return err + } + fmt.Printf("Security group: Removed security group rules [id=%s]\n", *sg.GroupId) } - fmt.Printf("Security group: Removed security group rules [id=%s]\n", *sg.GroupId) } for _, sg := range sgs.SecurityGroups { @@ -479,6 +523,20 @@ func realMain(ctx context.Context) error { return nil } +func vpcNameAndBuildURL(vpc *ec2.Vpc) (string, string) { + var vpcName string + var buildURL string + for _, tag := range vpc.Tags { + switch *tag.Key { + case "Name": + vpcName = *tag.Value + case buildURLTag: + buildURL = *tag.Value + } + } + return vpcName, buildURL +} + // destroyBackoff runs destroyF in a backoff loop. It logs each loop. func destroyBackoff(ctx context.Context, resourceKind string, resourceID string, destroyF func() error) error { start := time.Now() From 6bd1179a17ad12f01983d7bc94e25468ae74a7e1 Mon Sep 17 00:00:00 2001 From: jjwong <64273338+WJay-tec@users.noreply.github.com> Date: Sat, 9 Jul 2022 02:42:03 +0800 Subject: [PATCH 027/235] Adding podDistruptionBudget to connect injector (#1316) * Adding podDistruptionBudget to connect injector --- charts/consul/templates/_helpers.tpl | 14 ++ .../connect-injector-disruptionbudget.yaml | 26 +++ .../connect-injector-disruptionbudget.bats | 161 ++++++++++++++++++ charts/consul/values.yaml | 16 ++ 4 files changed, 217 insertions(+) create mode 100644 charts/consul/templates/connect-injector-disruptionbudget.yaml create mode 100755 charts/consul/test/unit/connect-injector-disruptionbudget.bats diff --git a/charts/consul/templates/_helpers.tpl b/charts/consul/templates/_helpers.tpl index 56f4fbf128..b667bdb460 100644 --- a/charts/consul/templates/_helpers.tpl +++ b/charts/consul/templates/_helpers.tpl @@ -197,6 +197,20 @@ Add a special case for replicas=1, where it should default to 0 as well. {{- end -}} {{- end -}} +{{- define "consul.pdb.connectInject.maxUnavailable" -}} +{{- if eq (int .Values.connectInject.replicas) 1 -}} +{{ 0 }} +{{- else if .Values.connectInject.disruptionBudget.maxUnavailable -}} +{{ .Values.server.disruptionBudget.maxUnavailable -}} +{{- else -}} +{{- if eq (int .Values.connectInject.replicas) 3 -}} +{{- 1 -}} +{{- else -}} +{{- sub (div (int .Values.connectInject.replicas) 2) 1 -}} +{{- end -}} +{{- end -}} +{{- end -}} + {{/* Inject extra environment vars in the format key:value, if populated */}} diff --git a/charts/consul/templates/connect-injector-disruptionbudget.yaml b/charts/consul/templates/connect-injector-disruptionbudget.yaml new file mode 100644 index 0000000000..08f1401fbe --- /dev/null +++ b/charts/consul/templates/connect-injector-disruptionbudget.yaml @@ -0,0 +1,26 @@ +{{- if (and .Values.connectInject.disruptionBudget.enabled (or (and (ne (.Values.connectInject.enabled | toString) "-") .Values.connectInject.enabled) (and (eq (.Values.connectInject.enabled | toString) "-") .Values.global.enabled))) }} +# PodDisruptionBudget to prevent degrading the connectInject cluster through +# voluntary cluster changes. +{{- if .Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }} +apiVersion: policy/v1 +{{- else }} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ template "consul.fullname" . }}-connect-injector + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: connect-injector +spec: + maxUnavailable: {{ template "consul.pdb.connectInject.maxUnavailable" . }} + selector: + matchLabels: + app: {{ template "consul.name" . }} + release: "{{ .Release.Name }}" + component: connect-injector +{{- end }} diff --git a/charts/consul/test/unit/connect-injector-disruptionbudget.bats b/charts/consul/test/unit/connect-injector-disruptionbudget.bats new file mode 100755 index 0000000000..ec998d0750 --- /dev/null +++ b/charts/consul/test/unit/connect-injector-disruptionbudget.bats @@ -0,0 +1,161 @@ +#!/usr/bin/env bats + +load _helpers + +@test "connect-injector/DisruptionBudget: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/connect-injector-disruptionbudget.yaml . +} + +@test "connect-injector/DisruptionBudget: enabled with connectInject=enabled , connectInject.disruptionBudget.enabled=true and global.enabled=true " { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connect-injector/DisruptionBudget: disabled with connectInject.enabled=false" { + cd `chart_dir` + assert_empty helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.enabled=false' \ + . +} + +@test "connect-injector/DisruptionBudget: disabled with connectInject.disruptionBudget.enabled=false" { + cd `chart_dir` + assert_empty helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.disruptionBudget.enabled=false' \ + . +} + +@test "connect-injector/DisruptionBudget: disabled with global.enabled=false" { + cd `chart_dir` + assert_empty helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'global.enabled=false' \ + . +} + +#-------------------------------------------------------------------- +# maxUnavailable + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=1" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=1' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "0" ] +} + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=3" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=3' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "1" ] +} + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=4" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=4' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "1" ] +} + + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=5" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=5' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "1" ] +} + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=6" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=6' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "2" ] +} + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=7" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=7' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "2" ] +} + +@test "connect-injector/DisruptionBudget: correct maxUnavailable with replicas=8" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --set 'connectInject.replicas=8' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.maxUnavailable' | tee /dev/stderr) + [ "${actual}" = "3" ] +} + +#-------------------------------------------------------------------- +# apiVersion + +@test "connect-injector/DisruptionBudget: uses policy/v1 if supported" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-injector-disruptionbudget.yaml \ + --api-versions 'policy/v1/PodDisruptionBudget' \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.disruptionBudget.enabled=true' \ + . | tee /dev/stderr | + yq -r '.apiVersion' | tee /dev/stderr) + [ "${actual}" = "policy/v1" ] +} +# NOTE: can't test that it uses policy/v1beta1 if policy/v1 is *not* supported +# because the supported API versions depends on the Helm version and there's +# no flag to *remove* an API version so some Helm versions will always have +# policy/v1 support and will always use that API version. + diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 1c756a951d..2079c41ad5 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -1860,6 +1860,22 @@ connectInject: # Note: This value has no effect if transparent proxy is disabled on the pod. defaultOverwriteProbes: true + # This configures the PodDisruptionBudget (https://kubernetes.io/docs/tasks/run-application/configure-pdb/) + # for the service mesh sidecar injector. + disruptionBudget: + # This will enable/disable registering a PodDisruptionBudget for the + # service mesh sidecar injector. If this is enabled, it will only register the budget so long as + # the service mesh is enabled. + enabled: true + + # The maximum number of unavailable pods. By default, this will be + # automatically computed based on the `connectInject.replicas` value to be `(n/2)-1`. + # If you need to set this to `0`, you will need to add a + # --set 'connectInject.disruptionBudget.maxUnavailable=0'` flag to the helm chart installation + # command because of a limitation in the Helm templating language. + # @type: integer + maxUnavailable: null + # Configures metrics for Consul Connect services. All values are overridable # via annotations on a per-pod basis. metrics: From c3ee5ff5792f2b1490e7be0cb71dbc4d3f3702fe Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Fri, 8 Jul 2022 14:09:50 -0500 Subject: [PATCH 028/235] update changelog (#1331) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bd8211e63..f6e4aca934 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ IMPROVEMENTS: * Added annotations `consul.hashicorp.com/consul-sidecar-user-volume` and `consul.hashicorp.com/consul-sidecar-user-volume-mount` for attaching Volumes and VolumeMounts to the Envoy sidecar. Both should be JSON objects. [[GH-1315](https://github.com/hashicorp/consul-k8s/pull/1315)] * Helm * Added `connectInject.annotations` and `syncCatalog.annotations` values for setting annotations on connect inject and sync catalog deployments. [[GH-775](https://github.com/hashicorp/consul-k8s/pull/775)] + * Added PodDisruptionBudget to the connect injector deployment which can be configured using the `connectInject.disruptionBudget` stanza. [[GH-1316](https://github.com/hashicorp/consul-k8s/pull/1316)] BUG FIXES: * Helm From 68e3ac18056ad9750bf04f0b0de7c2840b6509c6 Mon Sep 17 00:00:00 2001 From: Kyle Penfound Date: Tue, 12 Jul 2022 16:44:04 -0400 Subject: [PATCH 029/235] CRT Onboarding (#1290) * Release: enable using CRT for releases --- .github/workflows/build.yml | 47 ++++++++++++++++++------------------- .release/ci.hcl | 18 ++------------ 2 files changed, 25 insertions(+), 40 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 67b10fa9fb..3a87e25396 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,7 +8,6 @@ on: - main # Push events to branches matching refs/heads/release/** - "release/**" - - "cb/crt-testing" env: PKG_NAME: "consul-k8s-control-plane" @@ -68,29 +67,29 @@ jobs: matrix: include: # cli - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "386", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "cli", pkg_name: "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "386", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s.exe" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s.exe" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "cli", pkg_name: "consul-k8s", "bin_name": "consul-k8s" } # control-plane - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } # solaris is only built for the control plane - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "solaris", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "cli", pkg_name: "consul-k8s" } - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "solaris", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "386", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane.exe" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane.exe" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } fail-fast: true name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} ${{ matrix.component }} build @@ -110,7 +109,7 @@ jobs: working-directory: ${{ matrix.component }} run: | mkdir -p dist out - GCO_ENABLED=0 go build -o dist/${{ matrix.pkg_name }} . + CGO_ENABLED=0 go build -o dist/${{ matrix.bin_name }} . zip -r -j out/${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ - name: Upload built binaries @@ -203,7 +202,7 @@ jobs: steps: - uses: actions/checkout@v2 - name: Docker Build (Action) - uses: hashicorp/actions-docker-build@v1.2.1 + uses: hashicorp/actions-docker-build@v1 with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" diff --git a/.release/ci.hcl b/.release/ci.hcl index 9f25eafd9d..403ed13212 100644 --- a/.release/ci.hcl +++ b/.release/ci.hcl @@ -8,7 +8,7 @@ project "consul-k8s" { github { organization = "hashicorp" repository = "consul-k8s" - release_branches = ["cb/crt-testing"] + release_branches = ["main"] } } @@ -195,22 +195,8 @@ event "promote-staging" { } } -event "promote-staging-new-hc-releases" { - depends = ["promote-staging"] - action "promote-staging-new-hc-releases" { - organization = "hashicorp" - repository = "crt-workflows-common" - workflow = "promote-staging-new-hc-releases" - config = "release-metadata.hcl" - } - - notification { - on = "fail" - } -} - event "promote-staging-docker" { - depends = ["promote-staging-new-hc-releases"] + depends = ["promote-staging"] action "promote-staging-docker" { organization = "hashicorp" repository = "crt-workflows-common" From 77e3df1579190fe9fc00fad4f2186110a0d7a756 Mon Sep 17 00:00:00 2001 From: John Murret Date: Wed, 13 Jul 2022 17:58:03 -0600 Subject: [PATCH 030/235] Updating to go 1.18 (#1292) * Updating to go 1.18 * updating changelog, CI, and test dockerfile. * go mod tidy on /acceptance * go mod tidy on /cli * go mod tidy on /control-plane * go mod tidy on /hack/aws-acceptance-test-cleanup * go mod tidy on /hack/helm-reference-gen * updating golangci-lint-action to 3.2.0 * fixing golang version on charts/consul/test/docker/Test.dockerfile * updating .go-version to v1.18.3 * updating go testsum version to 1.8.1 * updating lint-control-plane to go install lint-consul-retry rather than go get lint-consul-retry. consul repo does this. * Updating changelog so that changes are listed under improvements rather than breaking changes. --- .circleci/config.yml | 8 +- .github/workflows/reusable-golangci-lint.yml | 4 +- .github/workflows/reusable-unit.yml | 2 +- .github/workflows/test.yml | 4 +- .go-version | 2 +- CHANGELOG.md | 6 + acceptance/go.mod | 2 +- acceptance/go.sum | 219 ------------------- charts/consul/test/docker/Test.dockerfile | 2 +- charts/go.mod | 2 +- cli/go.mod | 2 +- cli/go.sum | 3 - control-plane/go.mod | 2 +- control-plane/go.sum | 4 - hack/aws-acceptance-test-cleanup/go.mod | 6 +- hack/copy-crds-to-chart/go.mod | 2 +- hack/helm-reference-gen/go.mod | 7 +- 17 files changed, 33 insertions(+), 244 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8bae0f3ed2..a28ec66add 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ orbs: executors: go: docker: - - image: docker.mirror.hashicorp.services/cimg/go:1.17.9 + - image: docker.mirror.hashicorp.services/cimg/go:1.18.3 environment: TEST_RESULTS: /tmp/test-results # path to where test results are saved @@ -28,9 +28,9 @@ commands: - run: name: Install gotestsum, kind, kubectl, and helm command: | - wget https://golang.org/dl/go1.17.9.linux-amd64.tar.gz - sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.17.9.linux-amd64.tar.gz - rm go1.17.9.linux-amd64.tar.gz + wget https://golang.org/dl/go1.18.3.linux-amd64.tar.gz + sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz + rm go1.18.3.linux-amd64.tar.gz echo 'export PATH=$PATH:/usr/local/go/bin' >> $BASH_ENV wget https://github.com/gotestyourself/gotestsum/releases/download/v1.6.4/gotestsum_1.6.4_linux_amd64.tar.gz diff --git a/.github/workflows/reusable-golangci-lint.yml b/.github/workflows/reusable-golangci-lint.yml index 83f2449b30..c8c3793b03 100644 --- a/.github/workflows/reusable-golangci-lint.yml +++ b/.github/workflows/reusable-golangci-lint.yml @@ -27,8 +27,8 @@ jobs: go-version: ${{ inputs.go-version }} - name: golangci-lint-${{inputs.directory}} - uses: golangci/golangci-lint-action@v3.1.0 + uses: golangci/golangci-lint-action@v3.2.0 with: - version: v1.45.2 + version: v1.46.2 working-directory: ${{inputs.directory}} args: ${{inputs.args}} diff --git a/.github/workflows/reusable-unit.yml b/.github/workflows/reusable-unit.yml index 1183e1922c..9e563e0203 100644 --- a/.github/workflows/reusable-unit.yml +++ b/.github/workflows/reusable-unit.yml @@ -13,7 +13,7 @@ on: # Environment variables can only be used at the step level env: TEST_RESULTS: /tmp/test-results # path to where test results are saved - GOTESTSUM_VERSION: 1.6.4 + GOTESTSUM_VERSION: 1.8.1 jobs: job: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d69f40decb..b1703d3a41 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ env: TEST_RESULTS: /tmp/test-results # path to where test results are saved CONSUL_VERSION: 1.13.0-alpha1 # Consul's OSS version to use in tests CONSUL_ENT_VERSION: 1.13.0-alpha1+ent # Consul's enterprise version to use in tests - GOTESTSUM_VERSION: 1.6.4 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. + GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. jobs: get-go-version: @@ -97,7 +97,7 @@ jobs: with: go-version: ${{ needs.get-go-version.outputs.go-version }} - - run: go get -u github.com/hashicorp/lint-consul-retry && lint-consul-retry + - run: go install github.com/hashicorp/lint-consul-retry@master && lint-consul-retry - name: Run lint working-directory: control-plane diff --git a/.go-version b/.go-version index 19fb7bd9df..b9fb27ab4f 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.17.9 +1.18.3 diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e4aca934..1c4ebe9d1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ ## UNRELEASED +IMPROVEMENTS: +* Control Plane + * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] +* CLI + * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] + FEATURES: * [Experimental] Cluster Peering: diff --git a/acceptance/go.mod b/acceptance/go.mod index 2cc9576f61..494fc214d1 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/consul-k8s/acceptance -go 1.17 +go 1.18 require ( github.com/gruntwork-io/terratest v0.31.2 diff --git a/acceptance/go.sum b/acceptance/go.sum index 48012f8c78..7b40682c1e 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -17,7 +17,6 @@ cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -27,11 +26,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v35.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v38.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v46.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= @@ -46,7 +42,6 @@ github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMl github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.0/go.mod h1:QRTvSZQpxqm8mSErhnbI+tANIBAKP7B+UIE2z4ypUO0= github.com/Azure/go-autorest/autorest/azure/auth v0.5.1/go.mod h1:ea90/jvmnAwDrSooLH4sRIehEPtG/EPUXavDh31MnA4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.0/go.mod h1:JljT387FplPzBA31vUcvsetLKF3pec5bdAxjVU4kI2s= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= @@ -59,7 +54,6 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935 github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocmRAJWqST1wQYhyyjXJ3SJc= github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= -github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= @@ -75,19 +69,14 @@ github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jB github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -102,29 +91,19 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.16.26/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.25.37/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.25.41/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.1/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.27 h1:9gPjZWVDSoQrBO2AvqrWObS6KAZByfEJxQoCYo4ZfK0= github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8WK8raXaxBx6fRVTlJILwEwQGL1I/ByEI= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= -github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -134,11 +113,7 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= @@ -150,37 +125,26 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= -github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= -github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/digitalocean/godo v1.7.5/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= -github.com/digitalocean/godo v1.10.0/go.mod h1:h6faOIcZ8lWIwNQ+DN7b3CgX4Kwby5T+nbpNqkUIozU= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/cli v0.0.0-20191017083524-a8ff7f821017/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= @@ -207,10 +171,8 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= @@ -221,7 +183,6 @@ github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -232,7 +193,6 @@ github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -245,31 +205,25 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= github.com/go-ldap/ldap/v3 v3.1.10/go.mod h1:5Zun81jBTabRaI8lzN7E1JjyEl1g6zI6u9pd8luAK4Q= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -279,7 +233,6 @@ github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr6 github.com/go-test/deep v1.0.2 h1:onZX1rnHT3Wv6cqNgYyFOOlgVKJrksuCMCRvJStbMYw= github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= @@ -288,7 +241,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -311,10 +263,8 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -330,15 +280,11 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= -github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= @@ -350,7 +296,6 @@ github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= @@ -358,39 +303,29 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gruntwork-io/gruntwork-cli v0.7.0 h1:YgSAmfCj9c61H+zuvHwKfYUwlMhu5arnQQLM4RH+CYs= github.com/gruntwork-io/gruntwork-cli v0.7.0/go.mod h1:jp6Z7NcLF2avpY8v71fBx6hds9eOFPELSuD/VPv7w00= github.com/gruntwork-io/terratest v0.31.2 h1:xvYHA80MUq5kx670dM18HInewOrrQrAN+XbVVtytUHg= github.com/gruntwork-io/terratest v0.31.2/go.mod h1:EEgJie28gX/4AD71IFqgMj6e99KP5mi81hEtzmDjxTo= github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638 h1:z68s6H6O3RjxDmNvou/2/3UBrsJkrMcNzI0IQN5scAM= github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638/go.mod h1:7ZeaiADGbvJDuoWAT8UKj6KCcLsFUk+34OkUGMVtdXg= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20211116182834-e6956893fb6f/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0= github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228 h1:BqzKe5O+75uYcFfJI0mJz3rhCgdVztvEj3rEs4xpPr0= github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/consul/sdk v0.9.0 h1:NGSHAU7X3yDCjo8WBUbNOtD3BSqv8u0vu3+zNxgmxQI= github.com/hashicorp/consul/sdk v0.9.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= @@ -401,12 +336,10 @@ github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtng github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f/go.mod h1:D4eo8/CN92vm9/9UDG+ldX1/fMFa4kpl8qzyTolus8o= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -416,7 +349,6 @@ github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= -github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -427,7 +359,6 @@ github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es github.com/hashicorp/go-retryablehttp v0.6.2/go.mod h1:gEx6HMUGxYYhJScX7W1Il64m6cc2C1mDaW3NQ9sY1FY= github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= @@ -447,7 +378,6 @@ github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= @@ -455,16 +385,12 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= @@ -475,32 +401,21 @@ github.com/hashicorp/vault/api v1.2.0/go.mod h1:dAjw0T5shMnrfH7Q/Mst+LrcTKvStZBV github.com/hashicorp/vault/sdk v0.1.14-0.20200519221530-14615acda45f/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= github.com/hashicorp/vault/sdk v0.2.1 h1:S4O6Iv/dyKlE9AUTXGa7VOvZmsCvg36toPKgV4f2P4M= github.com/hashicorp/vault/sdk v0.2.1/go.mod h1:WfUiO1vYzfBkz1TmoE4ZGU7HD0T0Cl/rZwaxjBkgN4U= -github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= -github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= -github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a/go.mod h1:yL958EeXv8Ylng6IfnvG4oflryUi3vgA3xPs9hmII1s= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/joefitzgerald/rainbow-reporter v0.1.0/go.mod h1:481CNgqmVHQZzdIbN52CupLJyoVwB10FQ/IQlF1pdL8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/joyent/triton-go v0.0.0-20180628001255-830d2b111e62/go.mod h1:U+RSyWxWd04xTqnuOQxnai7XGS2PrPY2cfGoDKtMHjA= -github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f/go.mod h1:KDSfL7qe5ZfQqvlDMkVjCztbmcpp/c8M77vhQP8ZPvk= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -511,16 +426,13 @@ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMW github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -531,15 +443,11 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -554,13 +462,10 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/mattn/go-zglob v0.0.2-0.20190814121620-e3c945676326/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= -github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= @@ -569,7 +474,6 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -577,8 +481,6 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI= github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -591,7 +493,6 @@ github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8 github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -603,9 +504,7 @@ github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7P github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2/go.mod h1:TLb2Sg7HQcgGdloNxkrmtgDNR9uVYF3lfdFIN4Ro6Sk= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -616,9 +515,7 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.0-20180130162743-b8a9be070da4/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -644,9 +541,7 @@ github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zM github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/oracle/oci-go-sdk v7.1.0+incompatible/go.mod h1:VQb79nF8Z2cwLkLS35ukwStZIg5F66tcBccjip/j888= -github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -670,40 +565,25 @@ github.com/pquerna/otp v1.2.0 h1:/A3+Jn+cagqayeR3iHs/L62m5ue7710D35zl1zJ1kok= github.com/pquerna/otp v1.2.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= -github.com/renier/xmlrpc v0.0.0-20170708154548-ce4a1a486c03/go.mod h1:gRAiPF5C5Nd0eyyRdqIu9qTiFSoZzpTq727b5B8fkkU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rs/zerolog v1.4.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= -github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -713,35 +593,21 @@ github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkB github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24q7p+U= -github.com/sean-/conswriter v0.0.0-20180208195008-f5ae3917a627/go.mod h1:7zjs06qF79/FKAJpBvFx3P8Ww4UTIMAe+lpNXDHziac= -github.com/sean-/pager v0.0.0-20180208200047-666be9bf53b5/go.mod h1:BeybITEsBEg6qbIiqJ6/Bqeq25bCLbL7YFmpaFfJDuM= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= -github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/softlayer/softlayer-go v0.0.0-20180806151055-260589d94c7d/go.mod h1:Cw4GTlQccdRGSEf6KiMju767x0NEHE0YIVPJSaXjlsw= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -750,8 +616,6 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -762,18 +626,12 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= @@ -781,54 +639,26 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vdemeester/k8s-pkg-credentialprovider v0.0.0-20200107171650-7c61ffa44238/go.mod h1:JwQJCMWpUDqjZrB5jpw0f5VbN7U95zxFy1ZDpoEarGo= -github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -840,7 +670,6 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -884,7 +713,6 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -894,7 +722,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -913,13 +740,10 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= @@ -942,14 +766,12 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -964,7 +786,6 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -979,12 +800,10 @@ golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -996,27 +815,20 @@ golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= @@ -1039,7 +851,6 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1052,7 +863,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -1068,8 +878,6 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1088,7 +896,6 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1100,7 +907,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= @@ -1140,8 +946,6 @@ google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4 google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -1151,7 +955,6 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= @@ -1162,9 +965,6 @@ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= @@ -1197,7 +997,6 @@ gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1210,7 +1009,6 @@ gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1223,7 +1021,6 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1231,53 +1028,42 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= -k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= -k8s.io/apiextensions-apiserver v0.22.2/go.mod h1:2E0Ve/isxNl7tWLSUDgi6+cmwHi5fQRdwGVCxbC+KFA= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= -k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= k8s.io/apiserver v0.17.0/go.mod h1:ABM+9x/prjINN6iiffRVNCBR2Wk7uY4z+EtEGZD48cg= -k8s.io/apiserver v0.22.2/go.mod h1:vrpMmbyjWrgdyOvZTSpsusQq5iigKNWv9o9KlDAbBHI= k8s.io/client-go v0.17.0/go.mod h1:TYgR6EUHs6k45hb6KWjVD6jFZvJV4gHDikv/It0xz+k= -k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= k8s.io/client-go v0.19.3/go.mod h1:+eEMktZM+MG0KO+PTkci8xnbCZHvj9TqR6Q1XDUIJOM= k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= k8s.io/cloud-provider v0.17.0/go.mod h1:Ze4c3w2C0bRsjkBUoHpFi+qWe3ob1wI2/7cUn+YQIDE= k8s.io/code-generator v0.0.0-20191121015212-c4c8f8345c7e/go.mod h1:DVmfPQgxQENqDIzVR2ddLXMH34qeszkKSdH/N+s+38s= -k8s.io/code-generator v0.22.2/go.mod h1:eV77Y09IopzeXOJzndrDyCI88UBok2h6WxAlBwpxa+o= k8s.io/component-base v0.17.0/go.mod h1:rKuRAokNMY2nn2A6LP/MiwpoaMRHpfRnrPaUJJj1Yoc= -k8s.io/component-base v0.22.2/go.mod h1:5Br2QhI9OTe79p+TzPe9JKNQYvEKbq9rTJDWllunGug= k8s.io/csi-translation-lib v0.17.0/go.mod h1:HEF7MEz7pOLJCnxabi45IPkhSsE/KmxPQksuCrHKWls= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= -k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/legacy-cloud-providers v0.17.0/go.mod h1:DdzaepJ3RtRy+e5YhNtrCYwlgyK87j/5+Yfp0L9Syp8= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= @@ -1289,15 +1075,10 @@ modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/controller-runtime v0.10.2/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06 h1:zD2IemQ4LmOcAumeiyDWXKUI2SO0NYDe3H6QGvPOVgU= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= diff --git a/charts/consul/test/docker/Test.dockerfile b/charts/consul/test/docker/Test.dockerfile index ef6eb78c67..fdf51b162e 100644 --- a/charts/consul/test/docker/Test.dockerfile +++ b/charts/consul/test/docker/Test.dockerfile @@ -6,7 +6,7 @@ # a script to configure kubectl, potentially install Helm, and run the tests # manually. This image only has the dependencies pre-installed. -FROM circleci/golang:1.17 +FROM circleci/golang:1.18 # change the user to root so we can install stuff USER root diff --git a/charts/go.mod b/charts/go.mod index 950a1e55be..9c001ddad8 100644 --- a/charts/go.mod +++ b/charts/go.mod @@ -1,3 +1,3 @@ module github.com/hashicorp/consul-k8s/charts -go 1.17 +go 1.18 diff --git a/cli/go.mod b/cli/go.mod index 7e5ecba070..c8807e4be5 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/consul-k8s/cli -go 1.17 +go 1.18 require ( github.com/bgentry/speakeasy v0.1.0 diff --git a/cli/go.sum b/cli/go.sum index 1005b75ca9..c24ee30004 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -134,7 +134,6 @@ github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -923,7 +922,6 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -999,7 +997,6 @@ golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/control-plane/go.mod b/control-plane/go.mod index c4f5a31790..f95b55638c 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -131,4 +131,4 @@ require ( replace github.com/hashicorp/consul/sdk v0.9.0 => github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50 -go 1.17 +go 1.18 diff --git a/control-plane/go.sum b/control-plane/go.sum index b67416a74a..728ae24d43 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -105,7 +105,6 @@ github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -719,7 +718,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -795,7 +793,6 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= @@ -1002,7 +999,6 @@ k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8 k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= diff --git a/hack/aws-acceptance-test-cleanup/go.mod b/hack/aws-acceptance-test-cleanup/go.mod index 555d6d4269..a266c1a7e8 100644 --- a/hack/aws-acceptance-test-cleanup/go.mod +++ b/hack/aws-acceptance-test-cleanup/go.mod @@ -1,9 +1,13 @@ module github.com/hashicorp/consul-helm/hack/aws-acceptance-test-cleanup -go 1.16 +go 1.18 require ( github.com/aws/aws-sdk-go v1.38.63 github.com/cenkalti/backoff/v4 v4.1.1 +) + +require ( github.com/davecgh/go-spew v1.1.1 // indirect + github.com/jmespath/go-jmespath v0.4.0 // indirect ) diff --git a/hack/copy-crds-to-chart/go.mod b/hack/copy-crds-to-chart/go.mod index f88fccc7a9..5456f28ce2 100644 --- a/hack/copy-crds-to-chart/go.mod +++ b/hack/copy-crds-to-chart/go.mod @@ -1,3 +1,3 @@ module github.com/hashicorp/consul-k8s/hack/copy-crds-to-chart -go 1.16 +go 1.18 diff --git a/hack/helm-reference-gen/go.mod b/hack/helm-reference-gen/go.mod index 138cc52e5a..8595831de1 100644 --- a/hack/helm-reference-gen/go.mod +++ b/hack/helm-reference-gen/go.mod @@ -1,8 +1,13 @@ module github.com/hashicorp/consul-k8s/hack/helm-reference-gen -go 1.15 +go 1.18 require ( github.com/stretchr/testify v1.6.1 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 ) + +require ( + github.com/davecgh/go-spew v1.1.0 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect +) From 53221783dac718adee9808a9d4c34e6ec5e0b6ef Mon Sep 17 00:00:00 2001 From: John Murret Date: Fri, 15 Jul 2022 10:35:20 -0600 Subject: [PATCH 031/235] Replacing strings.Title with cases.Title to make broken CI linting pass (#1342) --- control-plane/subcommand/server-acl-init/command.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/control-plane/subcommand/server-acl-init/command.go b/control-plane/subcommand/server-acl-init/command.go index 988f9bb16e..93a6fefc31 100644 --- a/control-plane/subcommand/server-acl-init/command.go +++ b/control-plane/subcommand/server-acl-init/command.go @@ -21,6 +21,8 @@ import ( "github.com/hashicorp/go-hclog" "github.com/mitchellh/cli" "github.com/mitchellh/mapstructure" + "golang.org/x/text/cases" + "golang.org/x/text/language" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -755,7 +757,7 @@ func (c *Command) configureGateway(gatewayParams ConfigureGatewayParams, consulC for _, name := range gatewayParams.GatewayNames { if name == "" { errMessage := fmt.Sprintf("%s gateway name cannot be empty", - strings.Title(strings.ToLower(gatewayParams.GatewayType))) + cases.Title(language.English).String(gatewayParams.GatewayType)) c.log.Error(errMessage) return errors.New(errMessage) } From b000f6861cabfbfe6309cd1e3b9e967cfab087b4 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Mon, 18 Jul 2022 10:14:12 -0600 Subject: [PATCH 032/235] Disable wan federation tests on kind because of flakiness (#1346) Currently, WAN federation tests are flaky on kind. We need more time to investigate. Because these tests run on other clouds and are not flaky, we are disabling them on kind until we can investigate and re-enable them. --- acceptance/tests/mesh-gateway/main_test.go | 3 +++ acceptance/tests/vault/vault_wan_fed_test.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/acceptance/tests/mesh-gateway/main_test.go b/acceptance/tests/mesh-gateway/main_test.go index fb8935441e..1b57eb8552 100644 --- a/acceptance/tests/mesh-gateway/main_test.go +++ b/acceptance/tests/mesh-gateway/main_test.go @@ -15,6 +15,9 @@ func TestMain(m *testing.M) { if suite.Config().EnableMultiCluster { os.Exit(suite.Run()) + } else if suite.Config().UseKind { + fmt.Println("Skipping mesh gateway tests because they are currently flaky on kind") + os.Exit(0) } else { fmt.Println("Skipping mesh gateway tests because -enable-multi-cluster is not set") os.Exit(0) diff --git a/acceptance/tests/vault/vault_wan_fed_test.go b/acceptance/tests/vault/vault_wan_fed_test.go index 1d24614907..a58f45ee97 100644 --- a/acceptance/tests/vault/vault_wan_fed_test.go +++ b/acceptance/tests/vault/vault_wan_fed_test.go @@ -28,6 +28,9 @@ import ( // in the secondary that will treat the Vault server in the primary as an external server. func TestVault_WANFederationViaGateways(t *testing.T) { cfg := suite.Config() + if cfg.UseKind { + t.Skipf("Skipping this test because it's currently flaky on kind") + } if !cfg.EnableMultiCluster { t.Skipf("skipping this test because -enable-multi-cluster is not set") } From f8a33e0a5519319bde05f28f75ca248371f9e78f Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 19 Jul 2022 11:05:19 -0600 Subject: [PATCH 033/235] Actually disable mesh gateway tests on kind! (#1351) --- acceptance/tests/mesh-gateway/main_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/acceptance/tests/mesh-gateway/main_test.go b/acceptance/tests/mesh-gateway/main_test.go index 1b57eb8552..b7c6af4b90 100644 --- a/acceptance/tests/mesh-gateway/main_test.go +++ b/acceptance/tests/mesh-gateway/main_test.go @@ -13,11 +13,12 @@ var suite testsuite.Suite func TestMain(m *testing.M) { suite = testsuite.NewSuite(m) - if suite.Config().EnableMultiCluster { - os.Exit(suite.Run()) - } else if suite.Config().UseKind { + if suite.Config().UseKind { fmt.Println("Skipping mesh gateway tests because they are currently flaky on kind") os.Exit(0) + } + if suite.Config().EnableMultiCluster { + os.Exit(suite.Run()) } else { fmt.Println("Skipping mesh gateway tests because -enable-multi-cluster is not set") os.Exit(0) From 181ab2ce81505603afffcc46d4f39fa69f03f1ac Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 19 Jul 2022 11:09:18 -0600 Subject: [PATCH 034/235] Enable ubi images in the build workflow (#1350) --- .github/workflows/build.yml | 78 ++++++++++++++++++------------------- control-plane/Dockerfile | 6 ++- 2 files changed, 41 insertions(+), 43 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3a87e25396..7ca374a340 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,7 +10,7 @@ on: - "release/**" env: - PKG_NAME: "consul-k8s-control-plane" + PKG_NAME: "consul-k8s" jobs: get-go-version: @@ -189,7 +189,7 @@ jobs: name: ${{ env.DEB_PACKAGE }} path: out/${{ env.DEB_PACKAGE }} - build-docker-default: + build-docker: name: Docker ${{ matrix.arch }} default release build needs: [get-product-version, build] runs-on: ubuntu-latest @@ -221,44 +221,40 @@ jobs: docker.io/hashicorp/${{ env.repo }}-control-plane:${{ env.version }} 986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{ env.repo }}-control-plane:${{ env.version }} dev_tags: | - hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-dev + hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }} docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-${{ github.sha }} -# Disabling UBI build for now so that we do not inadvertently push a ubi image that we have not tested. - # build-docker-alternate: - # name: Docker ${{ matrix.arch }} alternate release build - # needs: [get-product-version, build] - # runs-on: ubuntu-latest - # strategy: - # matrix: - # arch: ["amd64"] - # env: - # repo: ${{ github.event.repository.name }} - # version: ${{ needs.get-product-version.outputs.product-version }} - # - # steps: - # - uses: actions/checkout@v2 - # - name: Copy LICENSE.md - # run: - # cp LICENSE.md ./control-plane - # - uses: hashicorp/actions-docker-build@v1.2.1 - # with: - # smoke_test: | - # TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" - # if [ "${TEST_VERSION}" != "${version}" ]; then - # echo "Test FAILED" - # exit 1 - # fi - # echo "Test PASSED" - # version: ${{ env.version }} - # target: ubi - # arch: ${{ matrix.arch }} - # pkg_name: consul-k8s-control-plane_${{ env.version }} - # bin_name: consul-k8s-control-plane - # workdir: control-plane - # tags: | - # registry.connect.redhat.com/hashicorp/consul-k8s-control-plane:${{env.version}}-ubi - # dev_tags: | - # hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi-dev - # docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi-${{ github.sha }} - # + build-docker-ubi: + name: Docker ${{ matrix.arch }} alternate release build + needs: [get-product-version, build] + runs-on: ubuntu-latest + strategy: + matrix: + arch: ["amd64"] + env: + repo: ${{ github.event.repository.name }} + version: ${{ needs.get-product-version.outputs.product-version }} + steps: + - uses: actions/checkout@v2 + - name: Copy LICENSE.md + run: + cp LICENSE.md ./control-plane + - uses: hashicorp/actions-docker-build@v1.2.1 + with: + smoke_test: | + TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" + if [ "${TEST_VERSION}" != "${version}" ]; then + echo "Test FAILED" + exit 1 + fi + echo "Test PASSED" + version: ${{ env.version }} + target: ubi + arch: ${{ matrix.arch }} + pkg_name: consul-k8s-control-plane_${{ env.version }} + bin_name: consul-k8s-control-plane + workdir: control-plane + redhat_tag: scan.connect.redhat.com/ospid-611ca2f89a9b407267837100/consul-k8s-control-plane:${{env.version}}-ubi + dev_tags: | + hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi + docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi-${{ github.sha }} diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 1a895c5e22..2d0ad412a6 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -85,7 +85,8 @@ ENV VERSION=${VERSION} RUN apk add --no-cache ca-certificates curl gnupg libcap openssl su-exec iputils libc6-compat iptables # TARGETOS and TARGETARCH are set automatically when --platform is provided. -ARG TARGETOS TARGETARCH +ARG TARGETOS +ARG TARGETARCH # Create a non-root user to run the software. RUN addgroup ${BIN_NAME} && \ @@ -126,7 +127,8 @@ ENV NAME=${BIN_NAME} ENV VERSION=${VERSION} # TARGETOS and TARGETARCH are set automatically when --platform is provided. -ARG TARGETOS TARGETARCH +ARG TARGETOS +ARG TARGETARCH # Copy license for Red Hat certification. COPY LICENSE.md /licenses/mozilla.txt From 688dbd89aced5a4723c9039beca9aa6e6828fdf7 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 19 Jul 2022 11:12:57 -0600 Subject: [PATCH 035/235] Add makefile target to prepare release (#1349) --- Makefile | 9 +++ .../build-support/functions/10-util.sh | 66 ++++++++++++++++++- 2 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index c18927bcf1..1029cd5bf2 100644 --- a/Makefile +++ b/Makefile @@ -99,6 +99,15 @@ ci.aws-acceptance-test-cleanup: ## Deletes AWS resources left behind after faile version: @echo $(VERSION) +# ===========> Release Targets + +prepare-release: ## Sets the versions, updates changelog to prepare this repository to release +ifndef RELEASE_VERSION + $(error RELEASE_VERSION is required) +endif + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; set_release_mode $(CURDIR) $(RELEASE_VERSION) "$(shell date +"%B %d, %Y")" $(PRERELEASE_VERSION) + + # ===========> Makefile config .DEFAULT_GOAL := help diff --git a/control-plane/build-support/functions/10-util.sh b/control-plane/build-support/functions/10-util.sh index a39b2307e7..31c8ce61ae 100644 --- a/control-plane/build-support/functions/10-util.sh +++ b/control-plane/build-support/functions/10-util.sh @@ -638,6 +638,52 @@ function update_version { return $? } +function update_version_helm { + # Arguments: + # $1 - Path to the directory where the root of the Helm chart is + # $2 - Version string + # $3 - PreRelease version (if unset will become an empty string) + # + # Returns: + # 0 - success + # * - error + + if ! test -d "$1" + then + err "ERROR: '$1' is not a directory. update_version_helm must be called with the path to the Helm chart" + return 1 + fi + + if test -z "$2" + then + err "ERROR: The version specified was empty" + return 1 + fi + + local vfile="$1/values.yaml" + local cfile="$1/Chart.yaml" + local version="$2" + local prerelease="$3" + local full_version="$2" + if ! test -z "$3" + then + full_version="$2-$3" + fi + local image_k8s="hashicorp\/consul-k8s-control-plane:$full_version" + + sed_i ${SED_EXT} -e "s/(imageK8S:[[:space:]]*)\"[^\"]*\"/\1${image_k8s}/g" "${vfile}" + sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(image:[[:space:]]*hashicorp\/consul-k8s-control-plane:)[^\"]*/\1${full_version}/g" "${cfile}" + + if test -z "$3" + then + sed_i ${SED_EXT} -e "s/(artifacthub.io\/prerelease:[[:space:]]*)[^\"]*/\1false/g" "${cfile}" + else + sed_i ${SED_EXT} -e "s/(artifacthub.io\/prerelease:[[:space:]]*)[^\"]*/\1true/g" "${cfile}" + fi + return $? +} + function set_changelog_version { # Arguments: # $1 - Path to top level Consul source @@ -744,6 +790,8 @@ function set_release_mode { return 1 fi + echo "release version: " $1 $2 $3 $4 + if test -z "$2" then err "ERROR: The version specified was empty" @@ -768,8 +816,22 @@ function set_release_mode { status_stage "==> Updating CHANGELOG.md with release info: ${changelog_vers} (${rel_date})" set_changelog_version "${sdir}" "${changelog_vers}" "${rel_date}" || return 1 - status_stage "==> Updating version/version.go" - if ! update_version "${sdir}/version/version.go" "${vers}" "$4" + status_stage "==> Updating control-plane version/version.go" + if ! update_version "${sdir}/control-plane/version/version.go" "${vers}" "$4" + then + unset_changelog_version "${sdir}" + return 1 + fi + + status_stage "==> Updating cli version/version.go" + if ! update_version "${sdir}/cli/version/version.go" "${vers}" "$4" + then + unset_changelog_version "${sdir}" + return 1 + fi + + status_stage "==> Updating Helm chart versions" + if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" then unset_changelog_version "${sdir}" return 1 From eaa82b3b82390fbf35137f5015db36a6f5a86871 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 19 Jul 2022 11:37:50 -0600 Subject: [PATCH 036/235] Fix UBI build (#1353) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7ca374a340..351e97a28c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -239,7 +239,7 @@ jobs: - name: Copy LICENSE.md run: cp LICENSE.md ./control-plane - - uses: hashicorp/actions-docker-build@v1.2.1 + - uses: hashicorp/actions-docker-build@v1 with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" From 3f5e94d466102970c6fb817dd2de8c8fbf88e140 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 19 Jul 2022 17:17:56 -0600 Subject: [PATCH 037/235] Skip peering tests on AKS and update AKS version (#1355) * On AKS, we cannot run peering tests yet because the pod network is not flat * Add a flag to acceptance tests framework to disable peering tests (to be removed once non-flat networks are supported) * Update AKS version to the supported 1.21.x version (1.21.7 is no longer supported) * Run AKS nightly acceptance tests with -disable-peering flag --- .circleci/config.yml | 2 +- acceptance/framework/config/config.go | 2 ++ acceptance/framework/flags/flags.go | 6 ++++++ acceptance/tests/peering/main_test.go | 4 ++-- charts/consul/test/terraform/aks/main.tf | 2 +- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a28ec66add..3f48eb9055 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -701,7 +701,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -disable-peering - store_test_results: path: /tmp/test-results diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index 1bda173025..62fd094a33 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -40,6 +40,8 @@ type TestConfig struct { EnableTransparentProxy bool + DisablePeering bool + ConsulImage string ConsulK8SImage string ConsulVersion *version.Version diff --git a/acceptance/framework/flags/flags.go b/acceptance/framework/flags/flags.go index 6565c2413d..b275bb0904 100644 --- a/acceptance/framework/flags/flags.go +++ b/acceptance/framework/flags/flags.go @@ -40,6 +40,8 @@ type TestFlags struct { flagUseKind bool + flagDisablePeering bool + once sync.Once } @@ -96,6 +98,8 @@ func (t *TestFlags) init() { flag.BoolVar(&t.flagUseKind, "use-kind", false, "If true, the tests will assume they are running against a local kind cluster(s).") + flag.BoolVar(&t.flagDisablePeering, "disable-peering", false, + "If true, the peering tests will not run.") if t.flagEnterpriseLicense == "" { t.flagEnterpriseLicense = os.Getenv("CONSUL_ENT_LICENSE") @@ -140,6 +144,8 @@ func (t *TestFlags) TestConfigFromFlags() *config.TestConfig { EnableTransparentProxy: t.flagEnableTransparentProxy, + DisablePeering: t.flagDisablePeering, + ConsulImage: t.flagConsulImage, ConsulK8SImage: t.flagConsulK8sImage, ConsulVersion: consulVersion, diff --git a/acceptance/tests/peering/main_test.go b/acceptance/tests/peering/main_test.go index fff59f1e70..12bb35afd5 100644 --- a/acceptance/tests/peering/main_test.go +++ b/acceptance/tests/peering/main_test.go @@ -13,10 +13,10 @@ var suite testsuite.Suite func TestMain(m *testing.M) { suite = testsuite.NewSuite(m) - if suite.Config().EnableMultiCluster { + if suite.Config().EnableMultiCluster && !suite.Config().DisablePeering { os.Exit(suite.Run()) } else { - fmt.Println("Skipping peering tests because -enable-multi-cluster is not set") + fmt.Println("Skipping peering tests because either -enable-multi-cluster is not set or -disable-peering is set") os.Exit(0) } } diff --git a/charts/consul/test/terraform/aks/main.tf b/charts/consul/test/terraform/aks/main.tf index e12ad64cf9..57de5d2a54 100644 --- a/charts/consul/test/terraform/aks/main.tf +++ b/charts/consul/test/terraform/aks/main.tf @@ -45,7 +45,7 @@ resource "azurerm_kubernetes_cluster" "default" { location = azurerm_resource_group.default[count.index].location resource_group_name = azurerm_resource_group.default[count.index].name dns_prefix = "consul-k8s-${random_id.suffix[count.index].dec}" - kubernetes_version = "1.21.7" + kubernetes_version = "1.21.14" // We're setting the network plugin and other network properties explicitly // here even though they are the same as defaults to ensure that none of these CIDRs From bce8f29fe0c2ca1fb794651b8359eee97a74acf7 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 19 Jul 2022 17:25:44 -0600 Subject: [PATCH 038/235] Build multi-arch dev-images (#1338) --- .circleci/config.yml | 23 ++++++++++++++--------- Makefile | 22 +++++++++++++++++++--- control-plane/Dockerfile | 5 +++-- control-plane/Makefile | 10 +++++----- 4 files changed, 41 insertions(+), 19 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3f48eb9055..4347e03b67 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -277,13 +277,18 @@ jobs: # upload dev docker image dev-upload-docker: - executor: go + machine: + image: ubuntu-2004:202010-01 + environment: + DOCKER_CLI_EXPERIMENTAL: enabled steps: - checkout # get consul-k8s binary - attach_workspace: at: . - - setup_remote_docker + - run: sudo apt-get update + - run: sudo apt-get install -y qemu-user-static + - run: docker buildx create --use - run: name: make ci.dev-docker working_directory: *control-plane-path @@ -983,13 +988,13 @@ workflows: # the summer of 2022 for larger puplic Github Action VMs be available before the acceptance tests can # be moved - build-distro: - OS: "darwin freebsd linux solaris windows" - ARCH: "amd64" - name: build-distros-amd64 + OS: "linux" + ARCH: "amd64 arm64" + name: build-distros-linux - dev-upload-docker: context: consul-ci requires: - - build-distros-amd64 + - build-distros-linux # Run acceptance tests using the docker image built for the control plane - acceptance: context: consul-ci @@ -1010,11 +1015,11 @@ workflows: jobs: - build-distro: OS: "linux" - ARCH: "amd64" - name: build-distros-amd64 + ARCH: "amd64 arm64" + name: build-distros-linux - dev-upload-docker: requires: - - build-distros-amd64 + - build-distros-linux - cleanup-gcp-resources - cleanup-azure-resources - cleanup-eks-resources diff --git a/Makefile b/Makefile index 1029cd5bf2..1522dbd442 100644 --- a/Makefile +++ b/Makefile @@ -19,14 +19,30 @@ control-plane-dev: ## Build consul-k8s-control-plane binary. control-plane-dev-docker: ## Build consul-k8s-control-plane dev Docker image. @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a $(GOARCH) - docker build -t '$(DEV_IMAGE)' \ + @docker build -t '$(DEV_IMAGE)' \ --target=dev \ - --build-arg 'ARCH=$(GOARCH)' \ + --build-arg 'TARGETARCH=$(GOARCH)' \ --build-arg 'GIT_COMMIT=$(GIT_COMMIT)' \ --build-arg 'GIT_DIRTY=$(GIT_DIRTY)' \ --build-arg 'GIT_DESCRIBE=$(GIT_DESCRIBE)' \ -f $(CURDIR)/control-plane/Dockerfile $(CURDIR)/control-plane +check-remote-dev-image-env: +ifndef REMOTE_DEV_IMAGE + $(error REMOTE_DEV_IMAGE is undefined: set this image to /:, e.g. hashicorp/consul-k8s-dev:latest) +endif + +control-plane-dev-docker-multi-arch: check-remote-dev-image-env ## Build consul-k8s-control-plane dev multi-arch Docker image. + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a "arm64 amd64" + @docker buildx create --use && docker buildx build -t '$(REMOTE_DEV_IMAGE)' \ + --platform linux/amd64,linux/arm64 \ + --target=dev \ + --build-arg 'GIT_COMMIT=$(GIT_COMMIT)' \ + --build-arg 'GIT_DIRTY=$(GIT_DIRTY)' \ + --build-arg 'GIT_DESCRIBE=$(GIT_DESCRIBE)' \ + --push \ + -f $(CURDIR)/control-plane/Dockerfile $(CURDIR)/control-plane + control-plane-test: ## Run go test for the control plane. cd control-plane; go test ./... @@ -67,7 +83,7 @@ acceptance-lint: ## Run linter in the control-plane directory. # ===========> Shared Targets help: ## Show targets and their descriptions. - @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-38s\033[0m %s\n", $$1, $$2}' lint: ## Run linter in the control-plane, cli, and acceptance directories. for p in control-plane cli acceptance; do cd $$p; golangci-lint run --path-prefix $$p -c ../.golangci.yml; cd ..; done diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 2d0ad412a6..633c8cbad0 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -21,7 +21,8 @@ FROM alpine:3.15 AS dev # and the version to download. Example: NAME=consul VERSION=1.2.3. ARG BIN_NAME=consul-k8s-control-plane ARG VERSION -ARG ARCH +ARG TARGETARCH +ARG TARGETOS LABEL name=${BIN_NAME} \ maintainer="Team Consul Kubernetes " \ @@ -41,7 +42,7 @@ RUN apk add --no-cache ca-certificates curl gnupg libcap openssl su-exec iputils RUN addgroup ${BIN_NAME} && \ adduser -S -G ${BIN_NAME} 100 -COPY pkg/bin/linux_${ARCH}/${BIN_NAME} /bin +COPY pkg/bin/linux_${TARGETARCH}/${BIN_NAME} /bin USER 100 CMD /bin/${BIN_NAME} diff --git a/control-plane/Makefile b/control-plane/Makefile index 2618ce535e..9c539228b7 100644 --- a/control-plane/Makefile +++ b/control-plane/Makefile @@ -32,16 +32,16 @@ ci.dev-tree: # should only run in CI and not locally. ci.dev-docker: @echo "Building consul-k8s Development container - $(CI_DEV_DOCKER_IMAGE_NAME)" - @docker build -t '$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT)' \ + @echo $(DOCKER_PASS) | docker login -u="$(DOCKER_USER)" --password-stdin + @docker buildx build -t '$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT)' \ + --platform linux/amd64,linux/arm64 \ --target=dev \ - --build-arg ARCH=amd64 \ + --push \ --label COMMIT_SHA=$(CIRCLE_SHA1) \ --label PULL_REQUEST=$(CIRCLE_PULL_REQUEST) \ --label CIRCLE_BUILD_URL=$(CIRCLE_BUILD_URL) \ $(CI_DEV_DOCKER_WORKDIR) -f $(CURDIR)/Dockerfile - @echo $(DOCKER_PASS) | docker login -u="$(DOCKER_USER)" --password-stdin - @echo "Pushing dev image to: https://cloud.docker.com/u/$(CI_DEV_DOCKER_NAMESPACE)/repository/docker/$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME)" - @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) + @echo "Pushed dev image to: $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT)" ifeq ($(CIRCLE_BRANCH), main) @docker tag $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest From 2030a4ee4cfc95965a82a633de8daf7ca8571f40 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 20 Jul 2022 11:08:59 -0600 Subject: [PATCH 039/235] Add a job to build and publish UBI images to dockerhub (#1356) --- .github/workflows/build.yml | 40 ++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 351e97a28c..8cf1e33d5b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -224,8 +224,8 @@ jobs: hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }} docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-${{ github.sha }} - build-docker-ubi: - name: Docker ${{ matrix.arch }} alternate release build + build-docker-ubi-redhat-registry: + name: Docker ${{ matrix.arch }} UBI build for RedHat Registry needs: [get-product-version, build] runs-on: ubuntu-latest strategy: @@ -255,6 +255,40 @@ jobs: bin_name: consul-k8s-control-plane workdir: control-plane redhat_tag: scan.connect.redhat.com/ospid-611ca2f89a9b407267837100/consul-k8s-control-plane:${{env.version}}-ubi + + build-docker-ubi-dockerhub: + name: Docker ${{ matrix.arch }} UBI build for DockerHub + needs: [ get-product-version, build ] + runs-on: ubuntu-latest + strategy: + matrix: + arch: [ "amd64" ] + env: + repo: ${{ github.event.repository.name }} + version: ${{ needs.get-product-version.outputs.product-version }} + steps: + - uses: actions/checkout@v2 + - name: Copy LICENSE.md + run: + cp LICENSE.md ./control-plane + - uses: hashicorp/actions-docker-build@v1 + with: + smoke_test: | + TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" + if [ "${TEST_VERSION}" != "${version}" ]; then + echo "Test FAILED" + exit 1 + fi + echo "Test PASSED" + version: ${{ env.version }} + target: ubi + arch: ${{ matrix.arch }} + pkg_name: consul-k8s-control-plane_${{ env.version }} + bin_name: consul-k8s-control-plane + workdir: control-plane + tags: | + docker.io/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi + 986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi dev_tags: | hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi - docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi-${{ github.sha }} + docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi-${{ github.sha }} From 66effda6d2cc7e833a39100f4a75430c6fce01e1 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 20 Jul 2022 11:11:09 -0600 Subject: [PATCH 040/235] Use buildx to push latest image tag from main (#1357) --- control-plane/Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/control-plane/Makefile b/control-plane/Makefile index 9c539228b7..c2177b722f 100644 --- a/control-plane/Makefile +++ b/control-plane/Makefile @@ -43,8 +43,15 @@ ci.dev-docker: $(CI_DEV_DOCKER_WORKDIR) -f $(CURDIR)/Dockerfile @echo "Pushed dev image to: $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT)" ifeq ($(CIRCLE_BRANCH), main) - @docker tag $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest - @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest + @docker buildx build -t '$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest' \ + --platform linux/amd64,linux/arm64 \ + --target=dev \ + --push \ + --label COMMIT_SHA=$(CIRCLE_SHA1) \ + --label PULL_REQUEST=$(CIRCLE_PULL_REQUEST) \ + --label CIRCLE_BUILD_URL=$(CIRCLE_BUILD_URL) \ + $(CI_DEV_DOCKER_WORKDIR) -f $(CURDIR)/Dockerfile + @echo "Pushed dev image to: $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest" endif # In Github Actions, the linux binary will be attached from a previous step at pkg/bin/linux_amd64/. This make target From bb8a612eb55457d3c23905aca0ad081f00b5e218 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 20 Jul 2022 13:41:31 -0400 Subject: [PATCH 041/235] Read created secrets from the API object (#1359) * Read created secrets from the API object - Avoid reading objects from the cache immediately after creating them as they are not guaranteed to exist. This leads to a bug caused by the race condition. - Add update RBAC to the secrets for the connect inject controller. * Update acceptance/tests/peering/peering_connect_test.go Co-authored-by: Iryna Shustava --- acceptance/tests/peering/peering_connect_test.go | 5 ++++- charts/consul/templates/connect-inject-clusterrole.yaml | 1 + .../connect-inject/peering_acceptor_controller.go | 8 +------- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index 5b67cc9b40..c156f0ee42 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -2,7 +2,6 @@ package peering import ( "context" - "github.com/hashicorp/go-version" "strconv" "testing" @@ -13,6 +12,7 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul/api" + "github.com/hashicorp/go-version" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -111,6 +111,9 @@ func TestPeering_Connect(t *testing.T) { helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { k8s.KubectlDelete(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") }) + acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") + require.NoError(t, err) + require.NotEmpty(t, acceptorSecretResourceVersion) // Copy secret from client peer to server peer. k8s.CopySecret(t, staticClientPeerClusterContext, staticServerPeerClusterContext, "api-token") diff --git a/charts/consul/templates/connect-inject-clusterrole.yaml b/charts/consul/templates/connect-inject-clusterrole.yaml index 1165782c4b..88194f4a61 100644 --- a/charts/consul/templates/connect-inject-clusterrole.yaml +++ b/charts/consul/templates/connect-inject-clusterrole.yaml @@ -52,6 +52,7 @@ rules: - "list" - "watch" - "create" + - "update" - "delete" - apiGroups: ["consul.hashicorp.com"] resources: ["peeringacceptors"] diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index dff8651fd5..5f4016f2c7 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -314,13 +314,7 @@ func (r *PeeringAcceptorController) createOrUpdateK8sSecret(ctx context.Context, return "", err } } - // The newly created or updated secret should exist at this point, so we can get it and return the resourceVersion. - newSecret := &corev1.Secret{} - if err := r.Client.Get(ctx, types.NamespacedName{Name: secretName, Namespace: secretNamespace}, newSecret); err != nil { - return "", err - } - - return newSecret.ResourceVersion, nil + return secret.ResourceVersion, nil } func (r *PeeringAcceptorController) deleteK8sSecret(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor) error { From daf5172b396ec361f9c272c9b5accf2e8e469f19 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 20 Jul 2022 11:57:14 -0600 Subject: [PATCH 042/235] Update CHANGELOG.md (#1360) --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c4ebe9d1f..6e1b2e3f99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ IMPROVEMENTS: BUG FIXES: * Helm * When using Openshift do not set securityContext in gossip-encryption-autogenerate job. [[GH-1308](https://github.com/hashicorp/consul-k8s/pull/1308)] +* Control Plane + * Fix missing RBAC permissions for the peering controllers to be able to update secrets. [[GH-1359](https://github.com/hashicorp/consul-k8s/pull/1359)] + * Fix a bug in the peering controller where we tried to read the secret from the cache right after creating it. [[GH-1359](https://github.com/hashicorp/consul-k8s/pull/1359)] ## 0.45.0 (June 17, 2022) FEATURES: From 4edec7cd9df14354a67b93d88694184ed8a1eb2d Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 20 Jul 2022 12:06:09 -0600 Subject: [PATCH 043/235] Pre-release 0.46.0 (#1361) --- .github/workflows/test.yml | 4 ++-- CHANGELOG.md | 2 +- charts/consul/Chart.yaml | 8 ++++---- charts/consul/values.yaml | 4 ++-- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b1703d3a41..e526e81137 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,8 +4,8 @@ on: env: TEST_RESULTS: /tmp/test-results # path to where test results are saved - CONSUL_VERSION: 1.13.0-alpha1 # Consul's OSS version to use in tests - CONSUL_ENT_VERSION: 1.13.0-alpha1+ent # Consul's enterprise version to use in tests + CONSUL_VERSION: 1.13.0-alpha2 # Consul's OSS version to use in tests + CONSUL_ENT_VERSION: 1.13.0-alpha2+ent # Consul's enterprise version to use in tests GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. jobs: diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e1b2e3f99..a229f0edc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.46.0 (July 20, 2022) IMPROVEMENTS: * Control Plane * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 0ae6e65478..d17bccc3fc 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul -version: 0.45.0 -appVersion: 1.12.2 +version: 0.46.0 +appVersion: 1.12.3 kubeVersion: ">=1.19.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -13,9 +13,9 @@ annotations: artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.12.2 + image: hashicorp/consul:1.12.3 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.45.0 + image: hashicorp/consul-k8s-control-plane:0.46.0 - name: envoy image: envoyproxy/envoy:v1.22.2 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 2079c41ad5..44e274c58d 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -93,7 +93,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.12.2" + image: "hashicorp/consul:1.12.3" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -113,7 +113,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: "hashicorp/consul-k8s-control-plane:0.45.0" + imageK8S: hashicorp/consul-k8s-control-plane:0.46.0 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 475688852a..f2c9daac5b 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.45.0" + Version = "0.46.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 475688852a..f2c9daac5b 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.45.0" + Version = "0.46.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 368d83f5d8fe363567a5bc78c675902a865f411f Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 20 Jul 2022 14:39:17 -0600 Subject: [PATCH 044/235] Pass correct compiler flags to go build for the release (#1362) --- .github/workflows/build.yml | 18 ++++++++++++------ cli/version/version.go | 1 + control-plane/version/version.go | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8cf1e33d5b..3b691fb307 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -109,7 +109,13 @@ jobs: working-directory: ${{ matrix.component }} run: | mkdir -p dist out - CGO_ENABLED=0 go build -o dist/${{ matrix.bin_name }} . + + export GIT_COMMIT=$(git rev-parse --short HEAD) + export GIT_DIRTY=$(test -n "$(git status --porcelain)" && echo "+CHANGES") + export GIT_IMPORT=github.com/hashicorp/consul-k8s/${{ matrix.component }}/version + export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${GIT_IMPORT}.GitDescribe=${{ needs.get-product-version.outputs.product-version }}" + + CGO_ENABLED=0 go build -o dist/${{ matrix.bin_name }} -ldflags "${GOLDFLAGS}" . zip -r -j out/${{ matrix.pkg_name }}_${{ needs.get-product-version.outputs.product-version }}_${{ matrix.goos }}_${{ matrix.goarch }}.zip dist/ - name: Upload built binaries @@ -150,7 +156,7 @@ jobs: cd /work rpm -ivh out/${{ env.RPM_PACKAGE }} CONSUL_K8S_VERSION="$(consul-k8s version | awk '{print $2}')" - VERSION="${{ needs.get-product-version.outputs.product-version }}" + VERSION="v${{ needs.get-product-version.outputs.product-version }}" if [ "${VERSION}" != "${CONSUL_K8S_VERSION}" ]; then echo "Test FAILED, expected: ${VERSION}, got: ${CONSUL_K8S_VERSION}" exit 1 @@ -175,7 +181,7 @@ jobs: cd /work apt install ./out/${{ env.DEB_PACKAGE }} CONSUL_K8S_VERSION="$(consul-k8s version | awk '{print $2}')" - VERSION="${{ needs.get-product-version.outputs.product-version }}" + VERSION="v${{ needs.get-product-version.outputs.product-version }}" if [ "${VERSION}" != "${CONSUL_K8S_VERSION}" ]; then echo "Test FAILED, expected: ${VERSION}, got: ${CONSUL_K8S_VERSION}" exit 1 @@ -206,7 +212,7 @@ jobs: with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" - if [ "${TEST_VERSION}" != "${version}" ]; then + if [ "${TEST_VERSION}" != "v${version}" ]; then echo "Test FAILED" exit 1 fi @@ -243,7 +249,7 @@ jobs: with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" - if [ "${TEST_VERSION}" != "${version}" ]; then + if [ "${TEST_VERSION}" != "v${version}" ]; then echo "Test FAILED" exit 1 fi @@ -275,7 +281,7 @@ jobs: with: smoke_test: | TEST_VERSION="$(docker run "${IMAGE_NAME}" consul-k8s-control-plane version | awk '{print $2}')" - if [ "${TEST_VERSION}" != "${version}" ]; then + if [ "${TEST_VERSION}" != "v${version}" ]; then echo "Test FAILED" exit 1 fi diff --git a/cli/version/version.go b/cli/version/version.go index f2c9daac5b..186b748ad1 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -29,6 +29,7 @@ func GetHumanVersion() string { if GitDescribe != "" { version = GitDescribe } + version = fmt.Sprintf("v%s", version) release := VersionPrerelease if GitDescribe == "" && release == "" { diff --git a/control-plane/version/version.go b/control-plane/version/version.go index f2c9daac5b..186b748ad1 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -29,6 +29,7 @@ func GetHumanVersion() string { if GitDescribe != "" { version = GitDescribe } + version = fmt.Sprintf("v%s", version) release := VersionPrerelease if GitDescribe == "" && release == "" { From 45901d13d0fddf9067ebd1cfb18854c1ef943943 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Thu, 21 Jul 2022 10:04:17 -0600 Subject: [PATCH 045/235] Remove ECR tags for docker images (#1364) --- .github/workflows/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3b691fb307..f7ac1521ba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -225,7 +225,6 @@ jobs: workdir: control-plane tags: | docker.io/hashicorp/${{ env.repo }}-control-plane:${{ env.version }} - 986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{ env.repo }}-control-plane:${{ env.version }} dev_tags: | hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }} docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-${{ github.sha }} @@ -294,7 +293,6 @@ jobs: workdir: control-plane tags: | docker.io/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi - 986891699432.dkr.ecr.us-east-1.amazonaws.com/hashicorp/${{ env.repo }}-control-plane:${{ env.version }}-ubi dev_tags: | hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi docker.io/hashicorppreview/${{ env.repo }}-control-plane:${{ env.version }}-ubi-${{ github.sha }} From d4b4de6d5e6b956137e861997a5edeb76af91b32 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Thu, 21 Jul 2022 10:37:43 -0600 Subject: [PATCH 046/235] Putting source back into Dev Mode (#1365) --- CHANGELOG.md | 2 ++ cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a229f0edc6..6fecaaab68 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.46.0 (July 20, 2022) IMPROVEMENTS: * Control Plane diff --git a/cli/version/version.go b/cli/version/version.go index 186b748ad1..e14f8e433f 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 186b748ad1..e14f8e433f 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 95c17e574e9d4d32b9c873f728afd712df494b5d Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Thu, 21 Jul 2022 13:01:23 -0400 Subject: [PATCH 047/235] Support Conditions on Peering CRDs (#1335) * Support Conditions on Peering CRDs - Add printer columns so describes have more metadata. * CHANGELOG --- .gitignore | 1 + CHANGELOG.md | 3 +- .../templates/crd-peeringacceptors.yaml | 65 +++++++++++++----- .../consul/templates/crd-peeringdialers.yaml | 65 +++++++++++++----- .../api/v1alpha1/peeringacceptor_types.go | 38 +++++++---- .../api/v1alpha1/peeringdialer_types.go | 31 +++++++-- .../api/v1alpha1/zz_generated.deepcopy.go | 65 ++++++------------ ...consul.hashicorp.com_peeringacceptors.yaml | 65 +++++++++++++----- .../consul.hashicorp.com_peeringdialers.yaml | 65 +++++++++++++----- .../peering_acceptor_controller.go | 39 +++++------ .../peering_acceptor_controller_test.go | 50 +++++++++----- .../peering_dialer_controller.go | 42 ++++-------- .../peering_dialer_controller_test.go | 68 +++++++++---------- 13 files changed, 363 insertions(+), 234 deletions(-) diff --git a/.gitignore b/.gitignore index 33b40aed54..8014afb2bf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .DS_Store .terraform/ .terraform.tfstate* +.terraform.lock.hcl terraform.tfstate* terraform.tfvars values.dev.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fecaaab68..275d77ed11 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ FEATURES: * [Experimental] Cluster Peering: * Add support for secret watchers on the Peering Acceptor and Peering Dialer controllers. [[GH-1284](https://github.com/hashicorp/consul-k8s/pull/1284)] * Add support for version annotation on the Peering Acceptor and Peering Dialer controllers. [[GH-1302](https://github.com/hashicorp/consul-k8s/pull/1302)] - * Add validation webhooks for the Peering Acceptor and Peering Dialer CRDs [[GH-1310](https://github.com/hashicorp/consul-k8s/pull/1310)] + * Add validation webhooks for the Peering Acceptor and Peering Dialer CRDs. [[GH-1310](https://github.com/hashicorp/consul-k8s/pull/1310)] + * Add Conditions to the status of the Peering Acceptor and Peering Dialer CRDs. [[GH-1335](https://github.com/hashicorp/consul-k8s/pull/1335)] IMPROVEMENTS: * Control Plane diff --git a/charts/consul/templates/crd-peeringacceptors.yaml b/charts/consul/templates/crd-peeringacceptors.yaml index 6cd7090ef7..e06e830f04 100644 --- a/charts/consul/templates/crd-peeringacceptors.yaml +++ b/charts/consul/templates/crd-peeringacceptors.yaml @@ -19,10 +19,25 @@ spec: kind: PeeringAcceptor listKind: PeeringAcceptorList plural: peeringacceptors + shortNames: + - peering-acceptor singular: peeringacceptor scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - description: The sync status of the resource with Consul + jsonPath: .status.conditions[?(@.type=="Synced")].status + name: Synced + type: string + - description: The last successful synced time of the resource with Consul + jsonPath: .status.lastSyncedTime + name: Last Synced + type: date + - description: The age of the resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 schema: openAPIV3Schema: description: PeeringAcceptor is the Schema for the peeringacceptors API. @@ -67,8 +82,39 @@ spec: status: description: PeeringAcceptorStatus defines the observed state of PeeringAcceptor. properties: - lastReconcileTime: - description: LastReconcileTime is the last time the resource was reconciled. + conditions: + description: Conditions indicate the latest available observations + of a resource's current state. + items: + description: 'Conditions define a readiness condition for a Consul + resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' + properties: + lastTransitionTime: + description: LastTransitionTime is the last time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition. + type: string + required: + - status + - type + type: object + type: array + lastSyncedTime: + description: LastSyncedTime is the last time the resource successfully + synced with Consul. format: date-time type: string latestPeeringVersion: @@ -76,19 +122,6 @@ spec: that was reconciled. format: int64 type: integer - reconcileError: - description: ReconcileError shows any errors during the last reconciliation - of this resource. - properties: - error: - description: Error is a boolean indicating if there was an error - during the last reconcile of this resource. - type: boolean - message: - description: Message displays the error message from the last - reconcile. - type: string - type: object secret: description: SecretRef shows the status of the secret. properties: diff --git a/charts/consul/templates/crd-peeringdialers.yaml b/charts/consul/templates/crd-peeringdialers.yaml index d5dee45f61..e24401e761 100644 --- a/charts/consul/templates/crd-peeringdialers.yaml +++ b/charts/consul/templates/crd-peeringdialers.yaml @@ -19,10 +19,25 @@ spec: kind: PeeringDialer listKind: PeeringDialerList plural: peeringdialers + shortNames: + - peering-dialer singular: peeringdialer scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - description: The sync status of the resource with Consul + jsonPath: .status.conditions[?(@.type=="Synced")].status + name: Synced + type: string + - description: The last successful synced time of the resource with Consul + jsonPath: .status.lastSyncedTime + name: Last Synced + type: date + - description: The age of the resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 schema: openAPIV3Schema: description: PeeringDialer is the Schema for the peeringdialers API. @@ -67,8 +82,39 @@ spec: status: description: PeeringDialerStatus defines the observed state of PeeringDialer. properties: - lastReconcileTime: - description: LastReconcileTime is the last time the resource was reconciled. + conditions: + description: Conditions indicate the latest available observations + of a resource's current state. + items: + description: 'Conditions define a readiness condition for a Consul + resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' + properties: + lastTransitionTime: + description: LastTransitionTime is the last time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition. + type: string + required: + - status + - type + type: object + type: array + lastSyncedTime: + description: LastSyncedTime is the last time the resource successfully + synced with Consul. format: date-time type: string latestPeeringVersion: @@ -76,19 +122,6 @@ spec: that was reconciled. format: int64 type: integer - reconcileError: - description: ReconcileError shows any errors during the last reconciliation - of this resource. - properties: - error: - description: Error is a boolean indicating if there was an error - during the last reconcile of this resource. - type: boolean - message: - description: Message displays the error message from the last - reconcile. - type: string - type: object secret: description: SecretRef shows the status of the secret. properties: diff --git a/control-plane/api/v1alpha1/peeringacceptor_types.go b/control-plane/api/v1alpha1/peeringacceptor_types.go index ad671a9e96..032870cb80 100644 --- a/control-plane/api/v1alpha1/peeringacceptor_types.go +++ b/control-plane/api/v1alpha1/peeringacceptor_types.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -20,6 +21,10 @@ func init() { //+kubebuilder:subresource:status // PeeringAcceptor is the Schema for the peeringacceptors API. +// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul" +// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" +// +kubebuilder:resource:shortName="peering-acceptor" type PeeringAcceptor struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -61,22 +66,17 @@ type Secret struct { type PeeringAcceptorStatus struct { // LatestPeeringVersion is the latest version of the resource that was reconciled. LatestPeeringVersion *uint64 `json:"latestPeeringVersion,omitempty"` - // LastReconcileTime is the last time the resource was reconciled. - // +optional - LastReconcileTime *metav1.Time `json:"lastReconcileTime,omitempty" description:"last time the resource was reconciled"` - // ReconcileError shows any errors during the last reconciliation of this resource. - // +optional - ReconcileError *ReconcileErrorStatus `json:"reconcileError,omitempty"` // SecretRef shows the status of the secret. // +optional SecretRef *SecretRefStatus `json:"secret,omitempty"` -} - -type ReconcileErrorStatus struct { - // Error is a boolean indicating if there was an error during the last reconcile of this resource. - Error *bool `json:"error,omitempty"` - // Message displays the error message from the last reconcile. - Message *string `json:"message,omitempty"` + // Conditions indicate the latest available observations of a resource's current state. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + Conditions Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` + // LastSyncedTime is the last time the resource successfully synced with Consul. + // +optional + LastSyncedTime *metav1.Time `json:"lastSyncedTime,omitempty" description:"last time the condition transitioned from one status to another"` } type SecretRefStatus struct { @@ -124,3 +124,15 @@ func (pa *PeeringAcceptor) Validate() error { } return nil } + +func (pa *PeeringAcceptor) SetSyncedCondition(status corev1.ConditionStatus, reason string, message string) { + pa.Status.Conditions = Conditions{ + { + Type: ConditionSynced, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + }, + } +} diff --git a/control-plane/api/v1alpha1/peeringdialer_types.go b/control-plane/api/v1alpha1/peeringdialer_types.go index 4998b27543..4ddde3fe2f 100644 --- a/control-plane/api/v1alpha1/peeringdialer_types.go +++ b/control-plane/api/v1alpha1/peeringdialer_types.go @@ -1,6 +1,7 @@ package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -19,6 +20,10 @@ func init() { //+kubebuilder:subresource:status // PeeringDialer is the Schema for the peeringdialers API. +// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type==\"Synced\")].status",description="The sync status of the resource with Consul" +// +kubebuilder:printcolumn:name="Last Synced",type="date",JSONPath=".status.lastSyncedTime",description="The last successful synced time of the resource with Consul" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="The age of the resource" +// +kubebuilder:resource:shortName="peering-dialer" type PeeringDialer struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -46,15 +51,17 @@ type PeeringDialerSpec struct { type PeeringDialerStatus struct { // LatestPeeringVersion is the latest version of the resource that was reconciled. LatestPeeringVersion *uint64 `json:"latestPeeringVersion,omitempty"` - // LastReconcileTime is the last time the resource was reconciled. - // +optional - LastReconcileTime *metav1.Time `json:"lastReconcileTime,omitempty" description:"last time the resource was reconciled"` - // ReconcileError shows any errors during the last reconciliation of this resource. - // +optional - ReconcileError *ReconcileErrorStatus `json:"reconcileError,omitempty"` // SecretRef shows the status of the secret. // +optional SecretRef *SecretRefStatus `json:"secret,omitempty"` + // Conditions indicate the latest available observations of a resource's current state. + // +optional + // +patchMergeKey=type + // +patchStrategy=merge + Conditions Conditions `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type"` + // LastSyncedTime is the last time the resource successfully synced with Consul. + // +optional + LastSyncedTime *metav1.Time `json:"lastSyncedTime,omitempty" description:"last time the condition transitioned from one status to another"` } func (pd *PeeringDialer) Secret() *Secret { @@ -99,3 +106,15 @@ func (pd *PeeringDialer) Validate() error { } return nil } + +func (pd *PeeringDialer) SetSyncedCondition(status corev1.ConditionStatus, reason string, message string) { + pd.Status.Conditions = Conditions{ + { + Type: ConditionSynced, + Status: status, + LastTransitionTime: metav1.Now(), + Reason: reason, + Message: message, + }, + } +} diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index 4806d72e6b..437ca89d1c 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -921,20 +921,22 @@ func (in *PeeringAcceptorStatus) DeepCopyInto(out *PeeringAcceptorStatus) { *out = new(uint64) **out = **in } - if in.LastReconcileTime != nil { - in, out := &in.LastReconcileTime, &out.LastReconcileTime - *out = (*in).DeepCopy() - } - if in.ReconcileError != nil { - in, out := &in.ReconcileError, &out.ReconcileError - *out = new(ReconcileErrorStatus) - (*in).DeepCopyInto(*out) - } if in.SecretRef != nil { in, out := &in.SecretRef, &out.SecretRef *out = new(SecretRefStatus) **out = **in } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LastSyncedTime != nil { + in, out := &in.LastSyncedTime, &out.LastSyncedTime + *out = (*in).DeepCopy() + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeeringAcceptorStatus. @@ -1034,20 +1036,22 @@ func (in *PeeringDialerStatus) DeepCopyInto(out *PeeringDialerStatus) { *out = new(uint64) **out = **in } - if in.LastReconcileTime != nil { - in, out := &in.LastReconcileTime, &out.LastReconcileTime - *out = (*in).DeepCopy() - } - if in.ReconcileError != nil { - in, out := &in.ReconcileError, &out.ReconcileError - *out = new(ReconcileErrorStatus) - (*in).DeepCopyInto(*out) - } if in.SecretRef != nil { in, out := &in.SecretRef, &out.SecretRef *out = new(SecretRefStatus) **out = **in } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(Conditions, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LastSyncedTime != nil { + in, out := &in.LastSyncedTime, &out.LastSyncedTime + *out = (*in).DeepCopy() + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PeeringDialerStatus. @@ -1151,31 +1155,6 @@ func (in *ProxyDefaultsSpec) DeepCopy() *ProxyDefaultsSpec { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReconcileErrorStatus) DeepCopyInto(out *ReconcileErrorStatus) { - *out = *in - if in.Error != nil { - in, out := &in.Error, &out.Error - *out = new(bool) - **out = **in - } - if in.Message != nil { - in, out := &in.Message, &out.Message - *out = new(string) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReconcileErrorStatus. -func (in *ReconcileErrorStatus) DeepCopy() *ReconcileErrorStatus { - if in == nil { - return nil - } - out := new(ReconcileErrorStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *RingHashConfig) DeepCopyInto(out *RingHashConfig) { *out = *in diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml index f2df1eb96b..e782ef472f 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_peeringacceptors.yaml @@ -12,10 +12,25 @@ spec: kind: PeeringAcceptor listKind: PeeringAcceptorList plural: peeringacceptors + shortNames: + - peering-acceptor singular: peeringacceptor scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - description: The sync status of the resource with Consul + jsonPath: .status.conditions[?(@.type=="Synced")].status + name: Synced + type: string + - description: The last successful synced time of the resource with Consul + jsonPath: .status.lastSyncedTime + name: Last Synced + type: date + - description: The age of the resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 schema: openAPIV3Schema: description: PeeringAcceptor is the Schema for the peeringacceptors API. @@ -60,8 +75,39 @@ spec: status: description: PeeringAcceptorStatus defines the observed state of PeeringAcceptor. properties: - lastReconcileTime: - description: LastReconcileTime is the last time the resource was reconciled. + conditions: + description: Conditions indicate the latest available observations + of a resource's current state. + items: + description: 'Conditions define a readiness condition for a Consul + resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' + properties: + lastTransitionTime: + description: LastTransitionTime is the last time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition. + type: string + required: + - status + - type + type: object + type: array + lastSyncedTime: + description: LastSyncedTime is the last time the resource successfully + synced with Consul. format: date-time type: string latestPeeringVersion: @@ -69,19 +115,6 @@ spec: that was reconciled. format: int64 type: integer - reconcileError: - description: ReconcileError shows any errors during the last reconciliation - of this resource. - properties: - error: - description: Error is a boolean indicating if there was an error - during the last reconcile of this resource. - type: boolean - message: - description: Message displays the error message from the last - reconcile. - type: string - type: object secret: description: SecretRef shows the status of the secret. properties: diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml index 8492acec3a..d5103252a5 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_peeringdialers.yaml @@ -12,10 +12,25 @@ spec: kind: PeeringDialer listKind: PeeringDialerList plural: peeringdialers + shortNames: + - peering-dialer singular: peeringdialer scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - description: The sync status of the resource with Consul + jsonPath: .status.conditions[?(@.type=="Synced")].status + name: Synced + type: string + - description: The last successful synced time of the resource with Consul + jsonPath: .status.lastSyncedTime + name: Last Synced + type: date + - description: The age of the resource + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 schema: openAPIV3Schema: description: PeeringDialer is the Schema for the peeringdialers API. @@ -60,8 +75,39 @@ spec: status: description: PeeringDialerStatus defines the observed state of PeeringDialer. properties: - lastReconcileTime: - description: LastReconcileTime is the last time the resource was reconciled. + conditions: + description: Conditions indicate the latest available observations + of a resource's current state. + items: + description: 'Conditions define a readiness condition for a Consul + resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties' + properties: + lastTransitionTime: + description: LastTransitionTime is the last time the condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. + type: string + reason: + description: The reason for the condition's last transition. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition. + type: string + required: + - status + - type + type: object + type: array + lastSyncedTime: + description: LastSyncedTime is the last time the resource successfully + synced with Consul. format: date-time type: string latestPeeringVersion: @@ -69,19 +115,6 @@ spec: that was reconciled. format: int64 type: integer - reconcileError: - description: ReconcileError shows any errors during the last reconciliation - of this resource. - properties: - error: - description: Error is a boolean indicating if there was an error - during the last reconcile of this resource. - type: boolean - message: - description: Message displays the error message from the last - reconcile. - type: string - type: object secret: description: SecretRef shows the status of the secret. properties: diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index 5f4016f2c7..da977d8e8a 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -34,7 +34,12 @@ type PeeringAcceptorController struct { context.Context } -const FinalizerName = "finalizers.consul.hashicorp.com" +const ( + FinalizerName = "finalizers.consul.hashicorp.com" + ConsulAgentError = "ConsulAgentError" + InternalError = "InternalError" + KubernetesError = "KubernetesError" +) //+kubebuilder:rbac:groups=consul.hashicorp.com,resources=peeringacceptors,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=consul.hashicorp.com,resources=peeringacceptors/status,verbs=get;update;patch @@ -100,7 +105,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ if statusSecretSet { existingStatusSecret, err = r.getExistingSecret(ctx, acceptor.SecretRef().Name, acceptor.Namespace) if err != nil { - r.updateStatusError(ctx, acceptor, err) + r.updateStatusError(ctx, acceptor, KubernetesError, err) return ctrl.Result{}, err } } @@ -124,7 +129,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ r.Log.Info("stale secret in status; deleting stale secret", "name", acceptor.Name) err := r.Client.Delete(ctx, existingStatusSecret) if err != nil { - r.updateStatusError(ctx, acceptor, err) + r.updateStatusError(ctx, acceptor, KubernetesError, err) return ctrl.Result{}, err } } @@ -132,13 +137,13 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ // Generate and store the peering token. var resp *api.PeeringGenerateTokenResponse if resp, err = r.generateToken(ctx, acceptor.Name); err != nil { - r.updateStatusError(ctx, acceptor, err) + r.updateStatusError(ctx, acceptor, ConsulAgentError, err) return ctrl.Result{}, err } if acceptor.Secret().Backend == "kubernetes" { secretResourceVersion, err = r.createOrUpdateK8sSecret(ctx, acceptor, resp) if err != nil { - r.updateStatusError(ctx, acceptor, err) + r.updateStatusError(ctx, acceptor, KubernetesError, err) return ctrl.Result{}, err } } @@ -160,7 +165,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ if statusSecretSet { shouldGenerate, nameChanged, err = shouldGenerateToken(acceptor, existingStatusSecret) if err != nil { - r.updateStatusError(ctx, acceptor, err) + r.updateStatusError(ctx, acceptor, InternalError, err) return ctrl.Result{}, err } } else { @@ -184,7 +189,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ if existingStatusSecret != nil { err := r.Client.Delete(ctx, existingStatusSecret) if err != nil { - r.updateStatusError(ctx, acceptor, err) + r.updateStatusError(ctx, acceptor, ConsulAgentError, err) return ctrl.Result{}, err } } @@ -243,11 +248,8 @@ func (r *PeeringAcceptorController) updateStatus(ctx context.Context, acceptor * Secret: *acceptor.Secret(), ResourceVersion: secretResourceVersion, } - acceptor.Status.LastReconcileTime = &metav1.Time{Time: time.Now()} - acceptor.Status.ReconcileError = &consulv1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), - } + acceptor.Status.LastSyncedTime = &metav1.Time{Time: time.Now()} + acceptor.SetSyncedCondition(corev1.ConditionTrue, "", "") if peeringVersionString, ok := acceptor.Annotations[annotationPeeringVersion]; ok { peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) if err != nil { @@ -266,13 +268,8 @@ func (r *PeeringAcceptorController) updateStatus(ctx context.Context, acceptor * } // updateStatusError updates the peeringAcceptor's ReconcileError in the status. -func (r *PeeringAcceptorController) updateStatusError(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor, reconcileErr error) { - acceptor.Status.ReconcileError = &consulv1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(true), - Message: pointerToString(reconcileErr.Error()), - } - - acceptor.Status.LastReconcileTime = &metav1.Time{Time: time.Now()} +func (r *PeeringAcceptorController) updateStatusError(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor, reason string, reconcileErr error) { + acceptor.SetSyncedCondition(corev1.ConditionFalse, reason, reconcileErr.Error()) err := r.Status().Update(ctx, acceptor) if err != nil { r.Log.Error(err, "failed to update PeeringAcceptor status", "name", acceptor.Name, "namespace", acceptor.Namespace) @@ -421,10 +418,6 @@ func createSecret(name, namespace, key, value string) *corev1.Secret { return secret } -func pointerToString(s string) *string { - return &s -} - // containsString returns true if s is in slice. func containsString(slice []string, s string) bool { for _, item := range slice { diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index 69599f84a5..8a38762c4e 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -979,9 +979,11 @@ func TestAcceptorUpdateStatus(t *testing.T) { }, ResourceVersion: "1234", }, - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionTrue, + }, }, }, }, @@ -1022,9 +1024,11 @@ func TestAcceptorUpdateStatus(t *testing.T) { }, ResourceVersion: "1234", }, - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionTrue, + }, }, }, }, @@ -1062,7 +1066,7 @@ func TestAcceptorUpdateStatus(t *testing.T) { require.Equal(t, tt.expStatus.SecretRef.Key, acceptor.SecretRef().Key) require.Equal(t, tt.expStatus.SecretRef.Backend, acceptor.SecretRef().Backend) require.Equal(t, tt.expStatus.SecretRef.ResourceVersion, acceptor.SecretRef().ResourceVersion) - require.Equal(t, *tt.expStatus.ReconcileError.Error, *acceptor.Status.ReconcileError.Error) + require.Equal(t, tt.expStatus.Conditions[0].Message, acceptor.Status.Conditions[0].Message) }) } @@ -1094,9 +1098,13 @@ func TestAcceptorUpdateStatusError(t *testing.T) { }, reconcileErr: errors.New("this is an error"), expStatus: v1alpha1.PeeringAcceptorStatus{ - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(true), - Message: pointerToString("this is an error"), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionFalse, + Reason: InternalError, + Message: "this is an error", + }, }, }, }, @@ -1117,17 +1125,23 @@ func TestAcceptorUpdateStatusError(t *testing.T) { }, }, Status: v1alpha1.PeeringAcceptorStatus{ - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionTrue, + }, }, }, }, reconcileErr: errors.New("this is an error"), expStatus: v1alpha1.PeeringAcceptorStatus{ - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(true), - Message: pointerToString("this is an error"), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionFalse, + Reason: InternalError, + Message: "this is an error", + }, }, }, }, @@ -1151,7 +1165,7 @@ func TestAcceptorUpdateStatusError(t *testing.T) { Scheme: s, } - controller.updateStatusError(context.Background(), tt.acceptor, tt.reconcileErr) + controller.updateStatusError(context.Background(), tt.acceptor, InternalError, tt.reconcileErr) acceptor := &v1alpha1.PeeringAcceptor{} acceptorName := types.NamespacedName{ @@ -1160,7 +1174,7 @@ func TestAcceptorUpdateStatusError(t *testing.T) { } err := fakeClient.Get(context.Background(), acceptorName, acceptor) require.NoError(t, err) - require.Equal(t, *tt.expStatus.ReconcileError.Error, *acceptor.Status.ReconcileError.Error) + require.Equal(t, tt.expStatus.Conditions[0].Message, acceptor.Status.Conditions[0].Message) }) } diff --git a/control-plane/connect-inject/peering_dialer_controller.go b/control-plane/connect-inject/peering_dialer_controller.go index a5f3e19094..ffa88e3d61 100644 --- a/control-plane/connect-inject/peering_dialer_controller.go +++ b/control-plane/connect-inject/peering_dialer_controller.go @@ -78,29 +78,18 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques } } - // TODO(peering): remove this once CRD validation exists. - secretSet := false - if dialer.Secret() != nil { - secretSet = true - } - if !secretSet { - err = errors.New("PeeringDialer spec.peer.secret was not set") - r.updateStatusError(ctx, dialer, err) - return ctrl.Result{}, err - } - // specSecret will be nil if the secret specified by the spec doesn't exist. var specSecret *corev1.Secret specSecret, err = r.getSecret(ctx, dialer.Secret().Name, dialer.Namespace) if err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, KubernetesError, err) return ctrl.Result{}, err } // If specSecret doesn't exist, error because we can only initiate peering if we have a token to initiate with. if specSecret == nil { err = errors.New("PeeringDialer spec.peer.secret does not exist") - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, InternalError, err) return ctrl.Result{}, err } @@ -115,7 +104,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques if secretRefSet { statusSecret, err = r.getSecret(ctx, dialer.SecretRef().Name, dialer.Namespace) if err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, KubernetesError, err) return ctrl.Result{}, err } } @@ -128,7 +117,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.Log.Info("the secret in status.secretRef doesn't exist or wasn't set, establishing peering with the existing spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) @@ -151,7 +140,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.Log.Info("status.secret exists, but the peering doesn't exist in Consul; establishing peering with the existing spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) @@ -165,7 +154,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.Log.Info("the version annotation was incremented; re-establishing peering with spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) @@ -177,14 +166,14 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.Log.Info("status.secret exists, but the peering doesn't exist in Consul; establishing peering with the existing spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) return ctrl.Result{}, err } } else if err != nil { - r.updateStatusError(ctx, dialer, err) + r.updateStatusError(ctx, dialer, InternalError, err) return ctrl.Result{}, err } } @@ -210,11 +199,8 @@ func (r *PeeringDialerController) updateStatus(ctx context.Context, dialer *cons Secret: *dialer.Spec.Peer.Secret, ResourceVersion: resourceVersion, } - dialer.Status.LastReconcileTime = &metav1.Time{Time: time.Now()} - dialer.Status.ReconcileError = &consulv1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), - } + dialer.Status.LastSyncedTime = &metav1.Time{Time: time.Now()} + dialer.SetSyncedCondition(corev1.ConditionTrue, "", "") if peeringVersionString, ok := dialer.Annotations[annotationPeeringVersion]; ok { peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) if err != nil { @@ -232,12 +218,8 @@ func (r *PeeringDialerController) updateStatus(ctx context.Context, dialer *cons return err } -func (r *PeeringDialerController) updateStatusError(ctx context.Context, dialer *consulv1alpha1.PeeringDialer, reconcileErr error) { - dialer.Status.ReconcileError = &consulv1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(true), - Message: pointerToString(reconcileErr.Error()), - } - dialer.Status.LastReconcileTime = &metav1.Time{Time: time.Now()} +func (r *PeeringDialerController) updateStatusError(ctx context.Context, dialer *consulv1alpha1.PeeringDialer, reason string, reconcileErr error) { + dialer.SetSyncedCondition(corev1.ConditionFalse, reason, reconcileErr.Error()) err := r.Status().Update(ctx, dialer) if err != nil { r.Log.Error(err, "failed to update PeeringDialer status", "name", dialer.Name, "namespace", dialer.Namespace) diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index bc530cbdce..efeaf784db 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -41,24 +41,6 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { expectDeletedK8sSecret *types.NamespacedName peeringExists bool }{ - "Errors when Secret is not set on the spec": { - k8sObjects: func() []runtime.Object { - dialer := &v1alpha1.PeeringDialer{ - ObjectMeta: metav1.ObjectMeta{ - Name: "peering", - Namespace: "default", - }, - Spec: v1alpha1.PeeringDialerSpec{ - Peer: &v1alpha1.Peer{ - Secret: nil, - }, - }, - } - return []runtime.Object{dialer} - }, - expErr: "PeeringDialer spec.peer.secret was not set", - peeringSecret: func(_ string) *corev1.Secret { return nil }, - }, "Errors when Secret set on the spec does not exist in the cluster": { k8sObjects: func() []runtime.Object { dialer := &v1alpha1.PeeringDialer{ @@ -845,9 +827,11 @@ func TestDialerUpdateStatus(t *testing.T) { }, ResourceVersion: "1234", }, - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionTrue, + }, }, }, }, @@ -888,9 +872,11 @@ func TestDialerUpdateStatus(t *testing.T) { }, ResourceVersion: "1234", }, - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionTrue, + }, }, }, }, @@ -928,7 +914,7 @@ func TestDialerUpdateStatus(t *testing.T) { require.Equal(t, tt.expStatus.SecretRef.Key, dialer.SecretRef().Key) require.Equal(t, tt.expStatus.SecretRef.Backend, dialer.SecretRef().Backend) require.Equal(t, tt.expStatus.SecretRef.ResourceVersion, dialer.SecretRef().ResourceVersion) - require.Equal(t, *tt.expStatus.ReconcileError.Error, *dialer.Status.ReconcileError.Error) + require.Equal(t, tt.expStatus.Conditions[0].Message, dialer.Status.Conditions[0].Message) }) } } @@ -959,9 +945,13 @@ func TestDialerUpdateStatusError(t *testing.T) { }, reconcileErr: errors.New("this is an error"), expStatus: v1alpha1.PeeringDialerStatus{ - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(true), - Message: pointerToString("this is an error"), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionFalse, + Reason: InternalError, + Message: "this is an error", + }, }, }, }, @@ -982,17 +972,23 @@ func TestDialerUpdateStatusError(t *testing.T) { }, }, Status: v1alpha1.PeeringDialerStatus{ - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(false), - Message: pointerToString(""), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionTrue, + }, }, }, }, reconcileErr: errors.New("this is an error"), expStatus: v1alpha1.PeeringDialerStatus{ - ReconcileError: &v1alpha1.ReconcileErrorStatus{ - Error: pointerToBool(true), - Message: pointerToString("this is an error"), + Conditions: v1alpha1.Conditions{ + { + Type: v1alpha1.ConditionSynced, + Status: corev1.ConditionFalse, + Reason: InternalError, + Message: "this is an error", + }, }, }, }, @@ -1016,7 +1012,7 @@ func TestDialerUpdateStatusError(t *testing.T) { Scheme: s, } - controller.updateStatusError(context.Background(), tt.dialer, tt.reconcileErr) + controller.updateStatusError(context.Background(), tt.dialer, InternalError, tt.reconcileErr) dialer := &v1alpha1.PeeringDialer{} dialerName := types.NamespacedName{ @@ -1025,7 +1021,7 @@ func TestDialerUpdateStatusError(t *testing.T) { } err := fakeClient.Get(context.Background(), dialerName, dialer) require.NoError(t, err) - require.Equal(t, *tt.expStatus.ReconcileError.Error, *dialer.Status.ReconcileError.Error) + require.Equal(t, tt.expStatus.Conditions[0].Message, dialer.Status.Conditions[0].Message) }) } From 6ebea212f609d7a7952646dbf64ad7893c30d5f7 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Mon, 25 Jul 2022 12:52:14 -0400 Subject: [PATCH 048/235] T-Proxy for peering tests (#1337) * Expose Server GRPC on port 8503 --- .circleci/config.yml | 8 ++-- .../peering_connect_namespaces_test.go | 44 +++++++++++++------ .../tests/peering/peering_connect_test.go | 37 +++++++++++----- .../templates/server-config-configmap.yaml | 3 +- .../templates/server-podsecuritypolicy.yaml | 2 + charts/consul/templates/server-service.yaml | 3 ++ .../consul/templates/server-statefulset.yaml | 5 +++ .../test/unit/server-podsecuritypolicy.bats | 4 +- .../consul/test/unit/server-statefulset.bats | 6 +-- 9 files changed, 77 insertions(+), 35 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 4347e03b67..b1bcce48c7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -651,7 +651,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy - store_test_results: path: /tmp/test-results @@ -706,7 +706,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -disable-peering + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -disable-peering -enable-transparent-proxy - store_test_results: path: /tmp/test-results @@ -767,7 +767,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy - store_test_results: path: /tmp/test-results @@ -862,7 +862,7 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy - store_test_results: path: /tmp/test-results - store_artifacts: diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index 1ee178dec2..57421a3f53 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -2,7 +2,7 @@ package peering import ( "context" - "github.com/hashicorp/go-version" + "fmt" "strconv" "testing" @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul/api" + "github.com/hashicorp/go-version" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -31,10 +32,6 @@ func TestPeering_ConnectNamespaces(t *testing.T) { t.Skipf("skipping this test because -enable-enterprise is not set") } - if cfg.EnableTransparentProxy { - t.Skipf("skipping this test because Transparent Proxy is enabled") - } - ver, err := version.NewVersion("1.13.0") require.NoError(t, err) if cfg.ConsulVersion != nil && cfg.ConsulVersion.LessThan(ver) { @@ -79,7 +76,7 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.peering.enabled": "true", "global.enableConsulNamespaces": "true", - "global.image": "hashicorp/consul-enterprise:1.13.0-alpha2-ent", + "global.image": "thisisnotashwin/consul@sha256:446aad6e02f66e3027756dfc0d34e8e6e2b11ac6ec5637b134b34644ca7cda64", "global.tls.enabled": "false", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -87,8 +84,8 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.acls.manageSystemACLs": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), - "connectInject.enabled": "true", - "connectInject.transparentProxy.defaultEnabled": "false", + "connectInject.enabled": "true", + // When mirroringK8S is set, this setting is ignored. "connectInject.consulNamespaces.consulDestinationNamespace": c.destinationNamespace, "connectInject.consulNamespaces.mirroringK8S": strconv.FormatBool(c.mirrorK8S), @@ -97,6 +94,9 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "meshGateway.replicas": "1", "controller.enabled": "true", + + "dns.enabled": "true", + "dns.enableRedirection": strconv.FormatBool(cfg.EnableTransparentProxy), } staticServerPeerHelmValues := map[string]string{ @@ -205,10 +205,14 @@ func TestPeering_ConnectNamespaces(t *testing.T) { k8s.DeployKustomize(t, staticServerOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-server-inject") logger.Log(t, "creating static-client deployments in client peer") - if c.destinationNamespace == defaultNamespace { - k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/default-namespace") + if cfg.EnableTransparentProxy { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-tproxy") } else { - k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/non-default-namespace") + if c.destinationNamespace == defaultNamespace { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/default-namespace") + } else { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/non-default-namespace") + } } // Check that both static-server and static-client have been injected and now have 2 containers. podList, err := staticServerPeerClusterContext.KubernetesClient(t).CoreV1().Pods(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{ @@ -255,7 +259,11 @@ func TestPeering_ConnectNamespaces(t *testing.T) { } logger.Log(t, "checking that connection is successful") - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + } denyAllIntention := &api.ServiceIntentionsConfigEntry{ Name: "*", @@ -274,7 +282,11 @@ func TestPeering_ConnectNamespaces(t *testing.T) { require.NoError(t, err) logger.Log(t, "checking that the connection is not successful because there's no allow intention") - k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionMultipleFailureMessages(t, staticClientOpts, staticClientName, false, []string{"curl: (56) Recv failure: Connection reset by peer", "curl: (52) Empty reply from server", "curl: (7) Failed to connect to static-server.ns1 port 80: Connection refused"}, "", fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + } intention := &api.ServiceIntentionsConfigEntry{ Name: staticServerName, @@ -302,7 +314,11 @@ func TestPeering_ConnectNamespaces(t *testing.T) { require.NoError(t, err) logger.Log(t, "checking that connection is successful") - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + } }) } } diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index c156f0ee42..b1b246aac5 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -2,6 +2,7 @@ package peering import ( "context" + "fmt" "strconv" "testing" @@ -22,10 +23,6 @@ func TestPeering_Connect(t *testing.T) { env := suite.Environment() cfg := suite.Config() - if cfg.EnableTransparentProxy { - t.Skipf("skipping this test because Transparent Proxy is enabled") - } - ver, err := version.NewVersion("1.13.0") require.NoError(t, err) if cfg.ConsulVersion != nil && cfg.ConsulVersion.LessThan(ver) { @@ -52,7 +49,7 @@ func TestPeering_Connect(t *testing.T) { commonHelmValues := map[string]string{ "global.peering.enabled": "true", - "global.image": "hashicorp/consul:1.13.0-alpha2", + "global.image": "thisisnotashwin/consul@sha256:446aad6e02f66e3027756dfc0d34e8e6e2b11ac6ec5637b134b34644ca7cda64", "global.tls.enabled": "false", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -60,13 +57,15 @@ func TestPeering_Connect(t *testing.T) { "global.acls.manageSystemACLs": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), - "connectInject.enabled": "true", - "connectInject.transparentProxy.defaultEnabled": "false", + "connectInject.enabled": "true", "meshGateway.enabled": "true", "meshGateway.replicas": "1", "controller.enabled": "true", + + "dns.enabled": "true", + "dns.enableRedirection": strconv.FormatBool(cfg.EnableTransparentProxy), } staticServerPeerHelmValues := map[string]string{ @@ -170,7 +169,11 @@ func TestPeering_Connect(t *testing.T) { k8s.DeployKustomize(t, staticServerOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-server-inject") logger.Log(t, "creating static-client deployments in client peer") - k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/default") + if cfg.EnableTransparentProxy { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-tproxy") + } else { + k8s.DeployKustomize(t, staticClientOpts, cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-peers/default") + } // Check that both static-server and static-client have been injected and now have 2 containers. podList, err := staticServerPeerClusterContext.KubernetesClient(t).CoreV1().Pods(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{ LabelSelector: "app=static-server", @@ -203,7 +206,11 @@ func TestPeering_Connect(t *testing.T) { k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/default") }) logger.Log(t, "checking that connection is successful") - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + } denyAllIntention := &api.ServiceIntentionsConfigEntry{ Name: "*", @@ -220,7 +227,11 @@ func TestPeering_Connect(t *testing.T) { require.NoError(t, err) logger.Log(t, "checking that the connection is not successful because there's no allow intention") - k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionMultipleFailureMessages(t, staticClientOpts, staticClientName, false, []string{"curl: (56) Recv failure: Connection reset by peer", "curl: (52) Empty reply from server", "curl: (7) Failed to connect to static-server.ns1 port 80: Connection refused"}, "", fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + } intention := &api.ServiceIntentionsConfigEntry{ Name: staticServerName, @@ -239,7 +250,11 @@ func TestPeering_Connect(t *testing.T) { require.NoError(t, err) logger.Log(t, "checking that connection is successful") - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") + } }) } } diff --git a/charts/consul/templates/server-config-configmap.yaml b/charts/consul/templates/server-config-configmap.yaml index 7e8a1a296a..c04a0c44e3 100644 --- a/charts/consul/templates/server-config-configmap.yaml +++ b/charts/consul/templates/server-config-configmap.yaml @@ -27,7 +27,8 @@ data: "data_dir": "/consul/data", "domain": "{{ .Values.global.domain }}", "ports": { - "serf_lan": {{ .Values.server.ports.serflan.port }} + "serf_lan": {{ .Values.server.ports.serflan.port }}, + "grpc": 8503 }, "recursors": {{ .Values.global.recursors | toJson }}, "retry_join": ["{{template "consul.fullname" . }}-server.{{ .Release.Namespace }}.svc:{{ .Values.server.ports.serflan.port }}"], diff --git a/charts/consul/templates/server-podsecuritypolicy.yaml b/charts/consul/templates/server-podsecuritypolicy.yaml index c037ee9b8e..507a07179f 100644 --- a/charts/consul/templates/server-podsecuritypolicy.yaml +++ b/charts/consul/templates/server-podsecuritypolicy.yaml @@ -35,6 +35,8 @@ spec: max: {{ .Values.server.ports.serflan.port }} - min: 8302 max: 8302 + - min: 8503 + max: 8503 {{- end }} hostIPC: false hostPID: false diff --git a/charts/consul/templates/server-service.yaml b/charts/consul/templates/server-service.yaml index a6003f9ec3..4b1c714c1b 100644 --- a/charts/consul/templates/server-service.yaml +++ b/charts/consul/templates/server-service.yaml @@ -39,6 +39,9 @@ spec: port: 8501 targetPort: 8501 {{- end }} + - name: grpc + port: 8503 + targetPort: 8503 - name: serflan-tcp protocol: "TCP" port: 8301 diff --git a/charts/consul/templates/server-statefulset.yaml b/charts/consul/templates/server-statefulset.yaml index 7caec15b21..42df4f2f58 100644 --- a/charts/consul/templates/server-statefulset.yaml +++ b/charts/consul/templates/server-statefulset.yaml @@ -334,6 +334,11 @@ spec: - name: https containerPort: 8501 {{- end }} + - containerPort: 8503 + {{- if .Values.server.exposeGossipAndRPCPorts }} + hostPort: 8503 + {{- end }} + name: grpc - name: serflan-tcp containerPort: {{ .Values.server.ports.serflan.port }} {{- if .Values.server.exposeGossipAndRPCPorts }} diff --git a/charts/consul/test/unit/server-podsecuritypolicy.bats b/charts/consul/test/unit/server-podsecuritypolicy.bats index a87980ee80..99902d1971 100644 --- a/charts/consul/test/unit/server-podsecuritypolicy.bats +++ b/charts/consul/test/unit/server-podsecuritypolicy.bats @@ -39,7 +39,7 @@ load _helpers --set 'server.exposeGossipAndRPCPorts=true' \ . | tee /dev/stderr | yq -c '.spec.hostPorts' | tee /dev/stderr) - [ "${actual}" = '[{"min":8300,"max":8300},{"min":8301,"max":8301},{"min":8302,"max":8302}]' ] + [ "${actual}" = '[{"min":8300,"max":8300},{"min":8301,"max":8301},{"min":8302,"max":8302},{"min":8503,"max":8503}]' ] } @test "server/PodSecurityPolicy: hostPort 8300, server.ports.serflan.port and 8302 allowed when exposeGossipAndRPCPorts=true" { @@ -51,5 +51,5 @@ load _helpers --set 'server.ports.serflan.port=8333' \ . | tee /dev/stderr | yq -c '.spec.hostPorts' | tee /dev/stderr) - [ "${actual}" = '[{"min":8300,"max":8300},{"min":8333,"max":8333},{"min":8302,"max":8302}]' ] + [ "${actual}" = '[{"min":8300,"max":8300},{"min":8333,"max":8333},{"min":8302,"max":8302},{"min":8503,"max":8503}]' ] } diff --git a/charts/consul/test/unit/server-statefulset.bats b/charts/consul/test/unit/server-statefulset.bats index 5e40fb7d2a..3063a0e905 100755 --- a/charts/consul/test/unit/server-statefulset.bats +++ b/charts/consul/test/unit/server-statefulset.bats @@ -657,7 +657,7 @@ load _helpers -s templates/server-statefulset.yaml \ . | tee /dev/stderr | yq -r '.spec.template.metadata.annotations."consul.hashicorp.com/config-checksum"' | tee /dev/stderr) - [ "${actual}" = 8c29e583455a2e8d0372cbb884f00214d8b4ccf31f1647aab119778707ab56f8 ] + [ "${actual}" = 04cc39bf3f56ff39a2f4ae188fc37fc54b7775a073e8f97111eb37a548d7e229 ] } @test "server/StatefulSet: adds config-checksum annotation when extraConfig is provided" { @@ -667,7 +667,7 @@ load _helpers --set 'server.extraConfig="{\"hello\": \"world\"}"' \ . | tee /dev/stderr | yq -r '.spec.template.metadata.annotations."consul.hashicorp.com/config-checksum"' | tee /dev/stderr) - [ "${actual}" = 66fb7e1b861234b5291a0f2e464610febb721b358e6a6985f9b17d7a459edc50 ] + [ "${actual}" = e8d2e9535eb6e69eedebef725a66a8b47fd8845a77772f0e19911d2273b9b804 ] } @test "server/StatefulSet: adds config-checksum annotation when config is updated" { @@ -677,7 +677,7 @@ load _helpers --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | yq -r '.spec.template.metadata.annotations."consul.hashicorp.com/config-checksum"' | tee /dev/stderr) - [ "${actual}" = 51c076418d5d7654ac239e16773cf4dbd3bc4af413db48e88340ca25536b57ad ] + [ "${actual}" = d5f4de988e9d51ff8ae91a24a1a990dc65ce046c0494836f6d0f0eae34108235 ] } #-------------------------------------------------------------------- From 38786d50435c2c518c84291bab7b3c75f3a1ca82 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Mon, 25 Jul 2022 14:55:35 -0600 Subject: [PATCH 049/235] acceptance: Add retry to resource deletion and wait for more for ELB deletion to propagate (#1368) --- acceptance/framework/consul/helm_cluster.go | 127 ++++++++++---------- hack/aws-acceptance-test-cleanup/main.go | 2 +- 2 files changed, 65 insertions(+), 64 deletions(-) diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index a6530c205b..bcd07ecf39 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -123,87 +123,88 @@ func (h *HelmCluster) Destroy(t *testing.T) { // always idempotently clean up resources in the cluster. _ = helm.DeleteE(t, h.helmOptions, h.releaseName, false) - // Force delete any pods that have h.releaseName in their name because sometimes - // graceful termination takes a long time and since this is an uninstall - // we don't care that they're stopped gracefully. - pods, err := h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(t, err) - for _, pod := range pods.Items { - if strings.Contains(pod.Name, h.releaseName) { - var gracePeriod int64 = 0 - err := h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod}) - if !errors.IsNotFound(err) { - require.NoError(t, err) + // Retry because sometimes certain resources (like PVC) take time to delete + // in cloud providers. + retry.RunWith(&retry.Counter{Wait: 1 * time.Second, Count: 600}, t, func(r *retry.R) { + // Force delete any pods that have h.releaseName in their name because sometimes + // graceful termination takes a long time and since this is an uninstall + // we don't care that they're stopped gracefully. + pods, err := h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) + require.NoError(t, err) + for _, pod := range pods.Items { + if strings.Contains(pod.Name, h.releaseName) { + var gracePeriod int64 = 0 + err := h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), pod.Name, metav1.DeleteOptions{GracePeriodSeconds: &gracePeriod}) + if !errors.IsNotFound(err) { + require.NoError(t, err) + } } } - } - // Delete PVCs. - err = h.kubernetesClient.CoreV1().PersistentVolumeClaims(h.helmOptions.KubectlOptions.Namespace).DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(t, err) + // Delete PVCs. + err = h.kubernetesClient.CoreV1().PersistentVolumeClaims(h.helmOptions.KubectlOptions.Namespace).DeleteCollection(context.Background(), metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) + require.NoError(t, err) - // Delete any serviceaccounts that have h.releaseName in their name. - sas, err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(t, err) - for _, sa := range sas.Items { - if strings.Contains(sa.Name, h.releaseName) { - err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), sa.Name, metav1.DeleteOptions{}) - if !errors.IsNotFound(err) { - require.NoError(t, err) + // Delete any serviceaccounts that have h.releaseName in their name. + sas, err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) + require.NoError(t, err) + for _, sa := range sas.Items { + if strings.Contains(sa.Name, h.releaseName) { + err := h.kubernetesClient.CoreV1().ServiceAccounts(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), sa.Name, metav1.DeleteOptions{}) + if !errors.IsNotFound(err) { + require.NoError(t, err) + } } } - } - // Delete any roles that have h.releaseName in their name. - roles, err := h.kubernetesClient.RbacV1().Roles(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(t, err) - for _, role := range roles.Items { - if strings.Contains(role.Name, h.releaseName) { - err := h.kubernetesClient.RbacV1().Roles(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), role.Name, metav1.DeleteOptions{}) - if !errors.IsNotFound(err) { - require.NoError(t, err) + // Delete any roles that have h.releaseName in their name. + roles, err := h.kubernetesClient.RbacV1().Roles(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) + require.NoError(t, err) + for _, role := range roles.Items { + if strings.Contains(role.Name, h.releaseName) { + err := h.kubernetesClient.RbacV1().Roles(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), role.Name, metav1.DeleteOptions{}) + if !errors.IsNotFound(err) { + require.NoError(t, err) + } } } - } - // Delete any rolebindings that have h.releaseName in their name. - roleBindings, err := h.kubernetesClient.RbacV1().RoleBindings(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(t, err) - for _, roleBinding := range roleBindings.Items { - if strings.Contains(roleBinding.Name, h.releaseName) { - err := h.kubernetesClient.RbacV1().RoleBindings(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), roleBinding.Name, metav1.DeleteOptions{}) - if !errors.IsNotFound(err) { - require.NoError(t, err) + // Delete any rolebindings that have h.releaseName in their name. + roleBindings, err := h.kubernetesClient.RbacV1().RoleBindings(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) + require.NoError(t, err) + for _, roleBinding := range roleBindings.Items { + if strings.Contains(roleBinding.Name, h.releaseName) { + err := h.kubernetesClient.RbacV1().RoleBindings(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), roleBinding.Name, metav1.DeleteOptions{}) + if !errors.IsNotFound(err) { + require.NoError(t, err) + } } } - } - // Delete any secrets that have h.releaseName in their name. - secrets, err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{}) - require.NoError(t, err) - for _, secret := range secrets.Items { - if strings.Contains(secret.Name, h.releaseName) { - err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), secret.Name, metav1.DeleteOptions{}) - if !errors.IsNotFound(err) { - require.NoError(t, err) + // Delete any secrets that have h.releaseName in their name. + secrets, err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{}) + require.NoError(t, err) + for _, secret := range secrets.Items { + if strings.Contains(secret.Name, h.releaseName) { + err := h.kubernetesClient.CoreV1().Secrets(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), secret.Name, metav1.DeleteOptions{}) + if !errors.IsNotFound(err) { + require.NoError(t, err) + } } } - } - // Delete any jobs that have h.releaseName in their name. - jobs, err := h.kubernetesClient.BatchV1().Jobs(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) - require.NoError(t, err) - for _, job := range jobs.Items { - if strings.Contains(job.Name, h.releaseName) { - err := h.kubernetesClient.BatchV1().Jobs(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), job.Name, metav1.DeleteOptions{}) - if !errors.IsNotFound(err) { - require.NoError(t, err) + // Delete any jobs that have h.releaseName in their name. + jobs, err := h.kubernetesClient.BatchV1().Jobs(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) + require.NoError(t, err) + for _, job := range jobs.Items { + if strings.Contains(job.Name, h.releaseName) { + err := h.kubernetesClient.BatchV1().Jobs(h.helmOptions.KubectlOptions.Namespace).Delete(context.Background(), job.Name, metav1.DeleteOptions{}) + if !errors.IsNotFound(err) { + require.NoError(t, err) + } } } - } - // Retry because sometimes certain resources (like PVC) take time to delete - // in cloud providers. - retry.RunWith(&retry.Counter{Wait: 1 * time.Second, Count: 600}, t, func(r *retry.R) { + // Verify all Consul Pods are deleted. pods, err = h.kubernetesClient.CoreV1().Pods(h.helmOptions.KubectlOptions.Namespace).List(context.Background(), metav1.ListOptions{LabelSelector: "release=" + h.releaseName}) require.NoError(r, err) diff --git a/hack/aws-acceptance-test-cleanup/main.go b/hack/aws-acceptance-test-cleanup/main.go index e24fd692ce..3c121dfa11 100644 --- a/hack/aws-acceptance-test-cleanup/main.go +++ b/hack/aws-acceptance-test-cleanup/main.go @@ -364,7 +364,7 @@ func realMain(ctx context.Context) error { return err } // Allow time for ELB deletion to propagate so that we can detach the internet gateway. - time.Sleep(1 * time.Second) + time.Sleep(10 * time.Second) fmt.Printf("ELB: Destroyed [id=%s]\n", *elbDescrip.LoadBalancerName) } From b3360f0b5120f17dfc5ac6663707cf1c49830fa0 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 26 Jul 2022 15:15:49 -0600 Subject: [PATCH 050/235] Add required UBI labels (#1367) --- control-plane/Dockerfile | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 633c8cbad0..a2d1d96e34 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -108,18 +108,25 @@ CMD /bin/${BIN_NAME} # We don't rebuild the software because we want the exact checksums and # binary signatures to match the software and our builds aren't fully # reproducible currently. -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.5 as ubi +FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 as ubi -# NAME and VERSION are the name of the software in releases.hashicorp.com -# and the version to download. Example: NAME=consul VERSION=1.2.3. +ARG PRODUCT_NAME +ARG PRODUCT_VERSION +ARG PRODUCT_REVISION ARG BIN_NAME -ARG VERSION -LABEL name=${BIN_NAME} \ +# PRODUCT_NAME and PRODUCT_VERSION are the name of the software on releases.hashicorp.com +# and the version to download. Example: PRODUCT_NAME=consul PRODUCT_VERSION=1.2.3. +ENV BIN_NAME=$BIN_NAME +ENV PRODUCT_VERSION=$PRODUCT_VERSION + +ARG PRODUCT_NAME=$BIN_NAME + +LABEL name=$PRODUCT_NAME \ maintainer="Team Consul Kubernetes " \ vendor="HashiCorp" \ - version=${VERSION} \ - release=${VERSION} \ + version=$PRODUCT_VERSION \ + release=$PRODUCT_VERSION \ summary="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." \ description="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." From e8df6a2369f0f746421c49cba153dff97fe4e62e Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 26 Jul 2022 16:04:47 -0600 Subject: [PATCH 051/235] Update alpine to 3.16 (#1372) --- CHANGELOG.md | 4 ++++ control-plane/Dockerfile | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 275d77ed11..c90cb5596c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +IMPROVEMENTS: +* Control Plane + * Update alpine to 3.16 in the Docker image. [[GH-1372](https://github.com/hashicorp/consul-k8s/pull/1372)] + ## 0.46.0 (July 20, 2022) IMPROVEMENTS: * Control Plane diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index a2d1d96e34..f572d37413 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -15,7 +15,7 @@ # ----------------------------------- # BIN_NAME is a requirement in the hashicorp docker github action -FROM alpine:3.15 AS dev +FROM alpine:3.16 AS dev # NAME and VERSION are the name of the software in releases.hashicorp.com # and the version to download. Example: NAME=consul VERSION=1.2.3. @@ -64,7 +64,7 @@ CMD /bin/${BIN_NAME} # We don't rebuild the software because we want the exact checksums and # binary signatures to match the software and our builds aren't fully # reproducible currently. -FROM alpine:3.15 AS release-default +FROM alpine:3.16 AS release-default # NAME and VERSION are the name of the software in releases.hashicorp.com # and the version to download. Example: NAME=consul VERSION=1.2.3. From e02d8a42978488f3eb51e008be880ba9ab568b2c Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 26 Jul 2022 16:25:28 -0600 Subject: [PATCH 052/235] Release 0.46.1 (#1373) --- CHANGELOG.md | 2 +- charts/consul/Chart.yaml | 4 ++-- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c90cb5596c..1d7c5c2db6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.46.1 (July 26, 2022) IMPROVEMENTS: * Control Plane diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index d17bccc3fc..527f5128eb 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.46.0 +version: 0.46.1 appVersion: 1.12.3 kubeVersion: ">=1.19.0-0" description: Official HashiCorp Consul Chart @@ -15,7 +15,7 @@ annotations: - name: consul image: hashicorp/consul:1.12.3 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.46.0 + image: hashicorp/consul-k8s-control-plane:0.46.1 - name: envoy image: envoyproxy/envoy:v1.22.2 artifacthub.io/license: MPL-2.0 diff --git a/cli/version/version.go b/cli/version/version.go index e14f8e433f..e0cd99c74a 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.46.0" + Version = "0.46.1" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index e14f8e433f..e0cd99c74a 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.46.0" + Version = "0.46.1" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 765f826484c7d8ac62e48a6f70104295e0628143 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 27 Jul 2022 09:17:20 -0600 Subject: [PATCH 053/235] Putting source back into Dev Mode (#1374) --- CHANGELOG.md | 2 ++ cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d7c5c2db6..2813f44cf1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.46.1 (July 26, 2022) IMPROVEMENTS: diff --git a/cli/version/version.go b/cli/version/version.go index e0cd99c74a..ce4f269c93 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index e0cd99c74a..ce4f269c93 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From dddd0bcc81555bd519573d93d9dc00491e41b401 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 27 Jul 2022 09:19:13 -0600 Subject: [PATCH 054/235] Remove unused dockerfiles (#1375) --- .../build-support/docker/Dev.dockerfile | 2 - .../build-support/docker/Release.dockerfile | 70 ------------------ .../docker/Release.ubi.dockerfile | 72 ------------------- 3 files changed, 144 deletions(-) delete mode 100644 control-plane/build-support/docker/Dev.dockerfile delete mode 100644 control-plane/build-support/docker/Release.dockerfile delete mode 100644 control-plane/build-support/docker/Release.ubi.dockerfile diff --git a/control-plane/build-support/docker/Dev.dockerfile b/control-plane/build-support/docker/Dev.dockerfile deleted file mode 100644 index 3fc6842cad..0000000000 --- a/control-plane/build-support/docker/Dev.dockerfile +++ /dev/null @@ -1,2 +0,0 @@ -FROM hashicorp/consul-k8s-control-plane:latest -COPY pkg/bin/linux_amd64/consul-k8s-control-plane /bin diff --git a/control-plane/build-support/docker/Release.dockerfile b/control-plane/build-support/docker/Release.dockerfile deleted file mode 100644 index b782bd579b..0000000000 --- a/control-plane/build-support/docker/Release.dockerfile +++ /dev/null @@ -1,70 +0,0 @@ -# This Dockerfile creates a production release image for the project. This -# downloads the release from releases.hashicorp.com and therefore requires that -# the release is published before building the Docker image. -# -# We don't rebuild the software because we want the exact checksums and -# binary signatures to match the software and our builds aren't fully -# reproducible currently. -FROM alpine:3.15 - -# NAME and VERSION are the name of the software in releases.hashicorp.com -# and the version to download. Example: NAME=consul VERSION=1.2.3. -ARG NAME -ARG VERSION - -LABEL name=$NAME \ - maintainer="Consul Team " \ - vendor="HashiCorp" \ - version=$VERSION \ - release=$VERSION \ - summary="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." \ - description="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." - -# Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD -ENV NAME=$NAME -ENV VERSION=$VERSION - -# This is the location of the releases. -ENV HASHICORP_RELEASES=https://releases.hashicorp.com - -# Create a non-root user to run the software. -RUN addgroup ${NAME} && \ - adduser -S -G ${NAME} 100 - -# Set up certificates, base tools, and software. -RUN set -eux && \ - apk add --no-cache ca-certificates curl gnupg libcap openssl su-exec iputils libc6-compat iptables && \ - BUILD_GPGKEY=C874011F0AB405110D02105534365D9472D7468F; \ - found=''; \ - for server in \ - hkp://p80.pool.sks-keyservers.net:80 \ - hkp://keyserver.ubuntu.com:80 \ - hkp://pgp.mit.edu:80 \ - ; do \ - echo "Fetching GPG key $BUILD_GPGKEY from $server"; \ - gpg --keyserver "$server" --recv-keys "$BUILD_GPGKEY" && found=yes && break; \ - done; \ - test -z "$found" && echo >&2 "error: failed to fetch GPG key $BUILD_GPGKEY" && exit 1; \ - mkdir -p /tmp/build && \ - cd /tmp/build && \ - apkArch="$(apk --print-arch)" && \ - case "${apkArch}" in \ - aarch64) ARCH='arm64' ;; \ - armhf) ARCH='arm' ;; \ - x86) ARCH='386' ;; \ - x86_64) ARCH='amd64' ;; \ - *) echo >&2 "error: unsupported architecture: ${apkArch} (see ${HASHICORP_RELEASES}/${NAME}/${VERSION}/)" && exit 1 ;; \ - esac && \ - wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_linux_${ARCH}.zip && \ - wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_SHA256SUMS && \ - wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_SHA256SUMS.sig && \ - gpg --batch --verify ${NAME}_${VERSION}_SHA256SUMS.sig ${NAME}_${VERSION}_SHA256SUMS && \ - grep ${NAME}_${VERSION}_linux_${ARCH}.zip ${NAME}_${VERSION}_SHA256SUMS | sha256sum -c && \ - unzip -d /bin ${NAME}_${VERSION}_linux_${ARCH}.zip && \ - cd /tmp && \ - rm -rf /tmp/build && \ - apk del gnupg openssl && \ - rm -rf /root/.gnupg - -USER 100 -CMD /bin/${NAME} diff --git a/control-plane/build-support/docker/Release.ubi.dockerfile b/control-plane/build-support/docker/Release.ubi.dockerfile deleted file mode 100644 index 95768a4c8d..0000000000 --- a/control-plane/build-support/docker/Release.ubi.dockerfile +++ /dev/null @@ -1,72 +0,0 @@ -# Dockerfile for consul-k8s with UBI as its base image. Used for running on -# OpenShift. -# -# This Dockerfile creates a production release image for the project. This -# downloads the release from releases.hashicorp.com and therefore requires that -# the release is published before building the Docker image. -# -# We don't rebuild the software because we want the exact checksums and -# binary signatures to match the software and our builds aren't fully -# reproducible currently. -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 - -# NAME and VERSION are the name of the software in releases.hashicorp.com -# and the version to download. Example: NAME=consul VERSION=1.2.3. -ARG NAME -ARG VERSION - -LABEL name=$NAME \ - maintainer="Consul Team " \ - vendor="HashiCorp" \ - version=$VERSION \ - release=$VERSION \ - summary="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." \ - description="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." - -# Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD -ENV NAME=$NAME -ENV VERSION=$VERSION - -# This is the location of the releases. -ENV HASHICORP_RELEASES=https://releases.hashicorp.com - -# Copy license for Red Hat certification. -COPY LICENSE.md /licenses/mozilla.txt - -# Set up certificates, base tools, and software. -RUN set -eux && \ - microdnf install -y ca-certificates curl gnupg libcap openssl wget unzip tar shadow-utils iptables && \ - BUILD_GPGKEY=C874011F0AB405110D02105534365D9472D7468F; \ - found=''; \ - for server in \ - hkp://p80.pool.sks-keyservers.net:80 \ - hkp://keyserver.ubuntu.com:80 \ - hkp://pgp.mit.edu:80 \ - ; do \ - echo "Fetching GPG key $BUILD_GPGKEY from $server"; \ - gpg --keyserver "$server" --recv-keys "$BUILD_GPGKEY" && found=yes && break; \ - done; \ - test -z "$found" && echo >&2 "error: failed to fetch GPG key $BUILD_GPGKEY" && exit 1; \ - mkdir -p /tmp/build && \ - cd /tmp/build && \ - ARCH=amd64 && \ - wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_linux_${ARCH}.zip && \ - wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_SHA256SUMS && \ - wget ${HASHICORP_RELEASES}/${NAME}/${VERSION}/${NAME}_${VERSION}_SHA256SUMS.sig && \ - gpg --batch --verify ${NAME}_${VERSION}_SHA256SUMS.sig ${NAME}_${VERSION}_SHA256SUMS && \ - grep ${NAME}_${VERSION}_linux_${ARCH}.zip ${NAME}_${VERSION}_SHA256SUMS | sha256sum -c && \ - unzip -d /bin ${NAME}_${VERSION}_linux_${ARCH}.zip && \ - cd /tmp && \ - rm -rf /tmp/build && \ - gpgconf --kill all && \ - rm -rf /root/.gnupg - -# Create a non-root user to run the software. On OpenShift, this -# will not matter since the container is run as a random user and group -# but this is kept for consistency with our other images. -RUN groupadd --gid 1000 ${NAME} && \ - adduser --uid 100 --system -g ${NAME} ${NAME} && \ - usermod -a -G root ${NAME} - -USER 100 -CMD /bin/${NAME} From 1cdfa296726557012e4b9a1954828700e16cab14 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 27 Jul 2022 13:05:55 -0400 Subject: [PATCH 055/235] Enable TLS on Consul Peering (#1366) --- .../peering_connect_namespaces_test.go | 10 ++- .../tests/peering/peering_connect_test.go | 13 ++- charts/consul/templates/client-daemonset.yaml | 26 ++++++ .../templates/server-config-configmap.yaml | 53 ++++++++++-- charts/consul/test/unit/client-daemonset.bats | 42 ++++++++++ .../test/unit/server-config-configmap.bats | 80 +++++++++++++++++++ 6 files changed, 212 insertions(+), 12 deletions(-) diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index 57421a3f53..ec932f2fe8 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/go-version" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -78,7 +79,7 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.image": "thisisnotashwin/consul@sha256:446aad6e02f66e3027756dfc0d34e8e6e2b11ac6ec5637b134b34644ca7cda64", - "global.tls.enabled": "false", + "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), "global.tls.enableAutoEncrypt": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -142,6 +143,13 @@ func TestPeering_ConnectNamespaces(t *testing.T) { k8s.KubectlDelete(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") }) + // Ensure the secret is created. + retry.Run(t, func(r *retry.R) { + acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") + require.NoError(r, err) + require.NotEmpty(r, acceptorSecretResourceVersion) + }) + // Copy secret from client peer to server peer. k8s.CopySecret(t, staticClientPeerClusterContext, staticServerPeerClusterContext, "api-token") diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index b1b246aac5..0749b2cdc0 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul/api" + "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/go-version" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -51,7 +52,7 @@ func TestPeering_Connect(t *testing.T) { "global.image": "thisisnotashwin/consul@sha256:446aad6e02f66e3027756dfc0d34e8e6e2b11ac6ec5637b134b34644ca7cda64", - "global.tls.enabled": "false", + "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), "global.tls.enableAutoEncrypt": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -110,9 +111,13 @@ func TestPeering_Connect(t *testing.T) { helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { k8s.KubectlDelete(t, staticClientPeerClusterContext.KubectlOptions(t), "../fixtures/bases/peering/peering-acceptor.yaml") }) - acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") - require.NoError(t, err) - require.NotEmpty(t, acceptorSecretResourceVersion) + + // Ensure the secret is created. + retry.Run(t, func(r *retry.R) { + acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") + require.NoError(r, err) + require.NotEmpty(r, acceptorSecretResourceVersion) + }) // Copy secret from client peer to server peer. k8s.CopySecret(t, staticClientPeerClusterContext, staticServerPeerClusterContext, "api-token") diff --git a/charts/consul/templates/client-daemonset.yaml b/charts/consul/templates/client-daemonset.yaml index 0747a1ab68..83f410fd0c 100644 --- a/charts/consul/templates/client-daemonset.yaml +++ b/charts/consul/templates/client-daemonset.yaml @@ -283,6 +283,31 @@ spec: {{- end }} -hcl='leave_on_terminate = true' \ {{- if .Values.global.tls.enabled }} + {{- if .Values.global.peering.enabled }} + {{- if .Values.global.secretsBackend.vault.enabled }} + -hcl='tls { defaults { ca_file = "/vault/secrets/serverca.crt" }}' \ + {{- else }} + -hcl='tls { defaults { ca_file = "/consul/tls/ca/tls.crt" }}' \ + {{- end }} + {{- if .Values.global.tls.enableAutoEncrypt }} + -hcl='auto_encrypt = {tls = true}' \ + -hcl="auto_encrypt = {ip_san = [\"$HOST_IP\",\"$POD_IP\"]}" \ + {{- else }} + -hcl='tls { defaults { cert_file = "/consul/tls/client/tls.crt" }}' \ + -hcl='tls { defaults { key_file = "/consul/tls/client/tls.key" }}' \ + {{- end }} + {{- if .Values.global.tls.verify }} + -hcl='tls { defaults { verify_outgoing = true }}' \ + {{- if not .Values.global.tls.enableAutoEncrypt }} + -hcl='tls { internal_rpc { verify_incoming = true }}' \ + -hcl='tls { internal_rpc { verify_server_hostname = true }}' \ + {{- end }} + {{- end }} + -hcl='ports { https = 8501 }' \ + {{- if .Values.global.tls.httpsOnly }} + -hcl='ports { http = -1 }' \ + {{- end }} + {{- else}} {{- if .Values.global.secretsBackend.vault.enabled }} -hcl='ca_file = "/vault/secrets/serverca.crt"' \ {{- else }} @@ -307,6 +332,7 @@ spec: -hcl='ports { http = -1 }' \ {{- end }} {{- end }} + {{- end }} {{- if .Values.client.grpc }} -hcl='ports { grpc = 8502 }' \ {{- end }} diff --git a/charts/consul/templates/server-config-configmap.yaml b/charts/consul/templates/server-config-configmap.yaml index c04a0c44e3..113a1df22a 100644 --- a/charts/consul/templates/server-config-configmap.yaml +++ b/charts/consul/templates/server-config-configmap.yaml @@ -87,14 +87,52 @@ data: {{- if .Values.global.tls.enabled }} tls-config.json: |- { - {{- if .Values.global.secretsBackend.vault.enabled }} - "ca_file": "/vault/secrets/serverca.crt", - "cert_file": "/vault/secrets/servercert.crt", - "key_file": "/vault/secrets/servercert.key", + {{- if .Values.global.peering.enabled }} + "tls": { + {{- if .Values.global.tls.verify }} + "internal_rpc": { + "verify_incoming": true, + "verify_server_hostname": true + }, + "grpc": { + "verify_incoming": false + }, + {{- end }} + "defaults": { + {{- if .Values.global.tls.verify }} + "verify_outgoing": true, + {{- end }} + {{- if .Values.global.secretsBackend.vault.enabled }} + "ca_file": "/vault/secrets/serverca.crt", + "cert_file": "/vault/secrets/servercert.crt", + "key_file": "/vault/secrets/servercert.key" + {{- else }} + "ca_file": "/consul/tls/ca/tls.crt", + "cert_file": "/consul/tls/server/tls.crt", + "key_file": "/consul/tls/server/tls.key" + {{- end }} + } + }, + {{- if .Values.global.tls.enableAutoEncrypt }} + "auto_encrypt": { + "allow_tls": true + }, + {{- end }} + "ports": { + {{- if .Values.global.tls.httpsOnly }} + "http": -1, + {{- end }} + "https": 8501 + } + {{- else }} + {{- if .Values.global.secretsBackend.vault.enabled }} + "ca_file": "/vault/secrets/serverca.crt", + "cert_file": "/vault/secrets/servercert.crt", + "key_file": "/vault/secrets/servercert.key", {{- else }} - "ca_file": "/consul/tls/ca/tls.crt", - "cert_file": "/consul/tls/server/tls.crt", - "key_file": "/consul/tls/server/tls.key", + "ca_file": "/consul/tls/ca/tls.crt", + "cert_file": "/consul/tls/server/tls.crt", + "key_file": "/consul/tls/server/tls.key", {{- end }} {{- if .Values.global.tls.enableAutoEncrypt }} "auto_encrypt": { @@ -112,6 +150,7 @@ data: {{- end }} "https": 8501 } + {{- end }} } {{- end }} {{- if .Values.ui.enabled }} diff --git a/charts/consul/test/unit/client-daemonset.bats b/charts/consul/test/unit/client-daemonset.bats index 7e3aaa4146..b4f1a46d96 100755 --- a/charts/consul/test/unit/client-daemonset.bats +++ b/charts/consul/test/unit/client-daemonset.bats @@ -899,6 +899,48 @@ load _helpers [ "${actual}" = "true" ] } +@test "client/DaemonSet: sets verify_* flags to true by default when global.tls.enabled and global.peering.enabled" { + cd `chart_dir` + local command=$(helm template \ + -s templates/client-daemonset.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | join(" ")' | tee /dev/stderr) + + local actual + actual=$(echo $command | jq -r '. | contains("tls { internal_rpc { verify_incoming = true }}")' | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $command | jq -r '. | contains("tls { defaults { verify_outgoing = true }}")' | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $command | jq -r '. | contains("tls { internal_rpc { verify_server_hostname = true }}")' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "client/DaemonSet: sets updated TLS config when global.tls.enabled and global.peering.enabled" { + cd `chart_dir` + local command=$(helm template \ + -s templates/client-daemonset.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | join(" ")' | tee /dev/stderr) + + local actual + actual=$(echo $command | jq -r '. | contains("tls { defaults { ca_file = \"/consul/tls/ca/tls.crt\" }}")' | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $command | jq -r '. | contains("tls { defaults { cert_file = \"/consul/tls/client/tls.crt\" }}")' | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $command | jq -r '. | contains("tls { defaults { key_file = \"/consul/tls/client/tls.key\" }}")' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + @test "client/DaemonSet: doesn't set the verify_* flags when global.tls.enabled is true and global.tls.verify is false" { cd `chart_dir` local command=$(helm template \ diff --git a/charts/consul/test/unit/server-config-configmap.bats b/charts/consul/test/unit/server-config-configmap.bats index 624fcdf2a2..9b6c4206de 100755 --- a/charts/consul/test/unit/server-config-configmap.bats +++ b/charts/consul/test/unit/server-config-configmap.bats @@ -700,6 +700,39 @@ load _helpers [ "${actual}" = '{"http":-1,"https":8501}' ] } +@test "server/ConfigMap: sets correct default configuration when global.tls.enabled and global.peering.enabled" { + cd `chart_dir` + local config=$(helm template \ + -s templates/server-config-configmap.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.data["tls-config.json"]' | tee /dev/stderr) + + local actual + actual=$(echo $config | jq -r .tls.defaults.ca_file | tee /dev/stderr) + [ "${actual}" = "/consul/tls/ca/tls.crt" ] + + actual=$(echo $config | jq -r .tls.defaults.cert_file | tee /dev/stderr) + [ "${actual}" = "/consul/tls/server/tls.crt" ] + + actual=$(echo $config | jq -r .tls.defaults.key_file | tee /dev/stderr) + [ "${actual}" = "/consul/tls/server/tls.key" ] + + actual=$(echo $config | jq -r .tls.internal_rpc.verify_incoming | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $config | jq -r .tls.defaults.verify_outgoing | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $config | jq -r .tls.internal_rpc.verify_server_hostname | tee /dev/stderr) + [ "${actual}" = "true" ] + + actual=$(echo $config | jq -c .ports | tee /dev/stderr) + [ "${actual}" = '{"http":-1,"https":8501}' ] +} + @test "server/ConfigMap: doesn't set verify_* configuration to true when global.tls.enabled and global.tls.verify is false" { cd `chart_dir` local config=$(helm template \ @@ -720,6 +753,25 @@ load _helpers [ "${actual}" = "null" ] } +@test "server/ConfigMap: doesn't set verify_* configuration to true when global.tls.enabled and global.peering.enabled and global.tls.verify is false" { + cd `chart_dir` + local config=$(helm template \ + -s templates/server-config-configmap.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.verify=false' \ + . | tee /dev/stderr | + yq -r '.data["tls-config.json"]' | tee /dev/stderr) + + local actual + actual=$(echo $config | jq -r .tls.internal_rpc | tee /dev/stderr) + [ "${actual}" = "null" ] + + actual=$(echo $config | jq -r .tls.defaults.verify_outgoing | tee /dev/stderr) + [ "${actual}" = "null" ] +} + @test "server/ConfigMap: HTTP port is not set in when httpsOnly is false" { cd `chart_dir` local actual=$(helm template \ @@ -774,6 +826,34 @@ load _helpers [ "${actual}" = "/vault/secrets/servercert.key" ] } +@test "server/ConfigMap: sets TLS file paths to point to vault secrets when Vault is enabled and global.peering.enabled" { + cd `chart_dir` + local object=$(helm template \ + -s templates/server-config-configmap.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enableAutoEncrypt=true' \ + --set 'global.datacenter=dc2' \ + --set 'global.secretsBackend.vault.enabled=true' \ + --set 'global.secretsBackend.vault.consulClientRole=test' \ + --set 'global.secretsBackend.vault.consulServerRole=foo' \ + --set 'global.secretsBackend.vault.consulCARole=test' \ + --set 'global.tls.caCert.secretName=pki_int/cert/ca' \ + --set 'server.serverCert.secretName=pki_int/issue/test' \ + . | tee /dev/stderr | + yq -r '.data["tls-config.json"]' | tee /dev/stderr) + + local actual=$(echo $object | jq -r .tls.defaults.ca_file | tee /dev/stderr) + [ "${actual}" = "/vault/secrets/serverca.crt" ] + + local actual=$(echo $object | jq -r .tls.defaults.cert_file | tee /dev/stderr) + [ "${actual}" = "/vault/secrets/servercert.crt" ] + + local actual=$(echo $object | jq -r .tls.defaults.key_file | tee /dev/stderr) + [ "${actual}" = "/vault/secrets/servercert.key" ] +} + @test "server/ConfigMap: when global.metrics.enableAgentMetrics=true, sets telemetry config" { cd `chart_dir` local actual=$(helm template \ From cdf488fe959f9e517ae31f8f348197113985454d Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 27 Jul 2022 13:12:14 -0400 Subject: [PATCH 056/235] Peering ACL support (#1343) --- CHANGELOG.md | 5 +- .../peering_connect_namespaces_test.go | 97 +++++++++---------- .../tests/peering/peering_connect_test.go | 66 +++++-------- .../consul/templates/server-acl-init-job.yaml | 3 + .../consul/test/unit/server-acl-init-job.bats | 31 ++++++ .../subcommand/server-acl-init/command.go | 6 ++ .../subcommand/server-acl-init/rules.go | 5 + .../subcommand/server-acl-init/rules_test.go | 44 ++++++++- 8 files changed, 165 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2813f44cf1..a9c1c8353f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +FEATURES: +* [Experimental] Cluster Peering: + * Add support for ACLs and TLS. [[GH-1343](https://github.com/hashicorp/consul-k8s/pull/1343)] [[GH-1366](https://github.com/hashicorp/consul-k8s/pull/1366)] + ## 0.46.1 (July 26, 2022) IMPROVEMENTS: @@ -13,7 +17,6 @@ IMPROVEMENTS: * CLI * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] - FEATURES: * [Experimental] Cluster Peering: * Add support for secret watchers on the Peering Acceptor and Peering Dialer controllers. [[GH-1284](https://github.com/hashicorp/consul-k8s/pull/1284)] diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index ec932f2fe8..78a1c58436 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -66,6 +66,24 @@ func TestPeering_ConnectNamespaces(t *testing.T) { true, false, }, + { + "default destination namespace", + defaultNamespace, + false, + true, + }, + { + "single destination namespace", + staticServerNamespace, + false, + true, + }, + { + "mirror k8s namespaces", + staticServerNamespace, + true, + true, + }, } for _, c := range cases { @@ -77,7 +95,7 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.peering.enabled": "true", "global.enableConsulNamespaces": "true", - "global.image": "thisisnotashwin/consul@sha256:446aad6e02f66e3027756dfc0d34e8e6e2b11ac6ec5637b134b34644ca7cda64", + "global.image": "thisisnotashwin/consul@sha256:b1d3f59406adf5fb9a3bee4ded058e619d3a186e83b2e2dc14d6da3f28a7073d", "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -266,61 +284,40 @@ func TestPeering_ConnectNamespaces(t *testing.T) { }) } - logger.Log(t, "checking that connection is successful") - if cfg.EnableTransparentProxy { - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) - } else { - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") - } + if c.ACLsAndAutoEncryptEnabled { + logger.Log(t, "checking that the connection is not successful because there's no allow intention") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionMultipleFailureMessages(t, staticClientOpts, staticClientName, false, []string{"curl: (56) Recv failure: Connection reset by peer", "curl: (52) Empty reply from server", fmt.Sprintf("curl: (7) Failed to connect to static-server.%s port 80: Connection refused", c.destinationNamespace)}, "", fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + } - denyAllIntention := &api.ServiceIntentionsConfigEntry{ - Name: "*", - Kind: api.ServiceIntentions, - Namespace: "*", - Sources: []*api.SourceIntention{ - { - Name: "*", - Namespace: "*", - Action: api.IntentionActionDeny, - Peer: staticClientPeer, + intention := &api.ServiceIntentionsConfigEntry{ + Name: staticServerName, + Kind: api.ServiceIntentions, + Namespace: staticServerNamespace, + Sources: []*api.SourceIntention{ + { + Name: staticClientName, + Namespace: staticClientNamespace, + Action: api.IntentionActionAllow, + Peer: staticClientPeer, + }, }, - }, - } - _, _, err = staticServerPeerClient.ConfigEntries().Set(denyAllIntention, &api.WriteOptions{}) - require.NoError(t, err) - - logger.Log(t, "checking that the connection is not successful because there's no allow intention") - if cfg.EnableTransparentProxy { - k8s.CheckStaticServerConnectionMultipleFailureMessages(t, staticClientOpts, staticClientName, false, []string{"curl: (56) Recv failure: Connection reset by peer", "curl: (52) Empty reply from server", "curl: (7) Failed to connect to static-server.ns1 port 80: Connection refused"}, "", fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) - } else { - k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") - } + } - intention := &api.ServiceIntentionsConfigEntry{ - Name: staticServerName, - Kind: api.ServiceIntentions, - Namespace: staticServerNamespace, - Sources: []*api.SourceIntention{ - { - Name: staticClientName, - Namespace: staticClientNamespace, - Action: api.IntentionActionAllow, - Peer: staticClientPeer, - }, - }, - } + // Set the destination namespace to be the same + // unless mirrorK8S is true. + if !c.mirrorK8S { + intention.Namespace = c.destinationNamespace + intention.Sources[0].Namespace = c.destinationNamespace + } - // Set the destination namespace to be the same - // unless mirrorK8S is true. - if !c.mirrorK8S { - intention.Namespace = c.destinationNamespace - intention.Sources[0].Namespace = c.destinationNamespace + logger.Log(t, "creating intentions in server peer") + _, _, err = staticServerPeerClient.ConfigEntries().Set(intention, &api.WriteOptions{}) + require.NoError(t, err) } - logger.Log(t, "creating intentions in server peer") - _, _, err = staticServerPeerClient.ConfigEntries().Set(intention, &api.WriteOptions{}) - require.NoError(t, err) - logger.Log(t, "checking that connection is successful") if cfg.EnableTransparentProxy { k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.%s.consul", c.destinationNamespace, staticServerPeer)) diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index 0749b2cdc0..d18d6bee70 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -40,6 +40,10 @@ func TestPeering_Connect(t *testing.T) { "default installation", false, }, + { + "secure installation", + true, + }, } for _, c := range cases { @@ -50,7 +54,7 @@ func TestPeering_Connect(t *testing.T) { commonHelmValues := map[string]string{ "global.peering.enabled": "true", - "global.image": "thisisnotashwin/consul@sha256:446aad6e02f66e3027756dfc0d34e8e6e2b11ac6ec5637b134b34644ca7cda64", + "global.image": "thisisnotashwin/consul@sha256:b1d3f59406adf5fb9a3bee4ded058e619d3a186e83b2e2dc14d6da3f28a7073d", "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -210,50 +214,32 @@ func TestPeering_Connect(t *testing.T) { helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { k8s.KubectlDeleteK(t, staticServerPeerClusterContext.KubectlOptions(t), "../fixtures/cases/crd-peers/default") }) - logger.Log(t, "checking that connection is successful") - if cfg.EnableTransparentProxy { - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) - } else { - k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, "http://localhost:1234") - } - denyAllIntention := &api.ServiceIntentionsConfigEntry{ - Name: "*", - Kind: api.ServiceIntentions, - Sources: []*api.SourceIntention{ - { - Name: "*", - Action: api.IntentionActionDeny, - Peer: staticClientPeer, + if c.ACLsAndAutoEncryptEnabled { + logger.Log(t, "checking that the connection is not successful because there's no allow intention") + if cfg.EnableTransparentProxy { + k8s.CheckStaticServerConnectionMultipleFailureMessages(t, staticClientOpts, staticClientName, false, []string{"curl: (56) Recv failure: Connection reset by peer", "curl: (52) Empty reply from server", "curl: (7) Failed to connect to static-server port 80: Connection refused"}, "", fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) + } else { + k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") + } + + intention := &api.ServiceIntentionsConfigEntry{ + Name: staticServerName, + Kind: api.ServiceIntentions, + Sources: []*api.SourceIntention{ + { + Name: staticClientName, + Action: api.IntentionActionAllow, + Peer: staticClientPeer, + }, }, - }, - } - _, _, err = staticServerPeerClient.ConfigEntries().Set(denyAllIntention, &api.WriteOptions{}) - require.NoError(t, err) - - logger.Log(t, "checking that the connection is not successful because there's no allow intention") - if cfg.EnableTransparentProxy { - k8s.CheckStaticServerConnectionMultipleFailureMessages(t, staticClientOpts, staticClientName, false, []string{"curl: (56) Recv failure: Connection reset by peer", "curl: (52) Empty reply from server", "curl: (7) Failed to connect to static-server.ns1 port 80: Connection refused"}, "", fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) - } else { - k8s.CheckStaticServerConnectionFailing(t, staticClientOpts, staticClientName, "http://localhost:1234") - } + } - intention := &api.ServiceIntentionsConfigEntry{ - Name: staticServerName, - Kind: api.ServiceIntentions, - Sources: []*api.SourceIntention{ - { - Name: staticClientName, - Action: api.IntentionActionAllow, - Peer: staticClientPeer, - }, - }, + logger.Log(t, "creating intentions in server peer") + _, _, err = staticServerPeerClient.ConfigEntries().Set(intention, &api.WriteOptions{}) + require.NoError(t, err) } - logger.Log(t, "creating intentions in server peer") - _, _, err = staticServerPeerClient.ConfigEntries().Set(intention, &api.WriteOptions{}) - require.NoError(t, err) - logger.Log(t, "checking that connection is successful") if cfg.EnableTransparentProxy { k8s.CheckStaticServerConnectionSuccessful(t, staticClientOpts, staticClientName, fmt.Sprintf("http://static-server.virtual.%s.consul", staticServerPeer)) diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index c736384a4e..8709b82af7 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -185,6 +185,9 @@ spec: -enable-partitions=true \ -partition={{ .Values.global.adminPartitions.name }} \ {{- end }} + {{- if .Values.global.peering.enabled }} + -enable-peering=true \ + {{- end }} {{- if (or (and (ne (.Values.dns.enabled | toString) "-") .Values.dns.enabled) (and (eq (.Values.dns.enabled | toString) "-") .Values.global.enabled)) }} -allow-dns=true \ {{- end }} diff --git a/charts/consul/test/unit/server-acl-init-job.bats b/charts/consul/test/unit/server-acl-init-job.bats index 8259ec1c36..7b442a2ef8 100644 --- a/charts/consul/test/unit/server-acl-init-job.bats +++ b/charts/consul/test/unit/server-acl-init-job.bats @@ -1386,6 +1386,37 @@ load _helpers [ "${actual}" = "true" ] } +#-------------------------------------------------------------------- +# cluster peering + +@test "serverACLInit/Job: cluster peering disabled by default" { + cd `chart_dir` + local object=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command' | tee /dev/stderr) + + local actual=$(echo $object | + yq 'any(contains("enable-peering"))' | tee /dev/stderr) + [ "${actual}" = "false" ] +} + +@test "serverACLInit/Job: cluster peering enabled when peering is enabled" { + cd `chart_dir` + local object=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command' | tee /dev/stderr) + + local actual=$(echo $object | + yq 'any(contains("enable-peering"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # admin partitions diff --git a/control-plane/subcommand/server-acl-init/command.go b/control-plane/subcommand/server-acl-init/command.go index 93a6fefc31..ddf9b32ba3 100644 --- a/control-plane/subcommand/server-acl-init/command.go +++ b/control-plane/subcommand/server-acl-init/command.go @@ -79,6 +79,9 @@ type Command struct { flagPartitionName string // name of the Admin Partition flagPartitionTokenFile string + // Flags to support peering. + flagEnablePeering bool // true if Cluster Peering is enabled + // Flags to support namespaces. flagEnableNamespaces bool // Use namespacing on all components flagConsulSyncDestinationNamespace string // Consul namespace to register all catalog sync services into if not mirroring @@ -181,6 +184,9 @@ func (c *Command) init() { c.flags.StringVar(&c.flagPartitionTokenFile, "partition-token-file", "", "[Enterprise Only] Path to file containing ACL token to be used in non-default partitions.") + c.flags.BoolVar(&c.flagEnablePeering, "enable-peering", false, + "Enables Cluster Peering.") + c.flags.BoolVar(&c.flagEnableNamespaces, "enable-namespaces", false, "[Enterprise Only] Enables namespaces, in either a single Consul namespace or mirrored [Enterprise only feature]") c.flags.StringVar(&c.flagConsulSyncDestinationNamespace, "consul-sync-destination-namespace", consulDefaultNamespace, diff --git a/control-plane/subcommand/server-acl-init/rules.go b/control-plane/subcommand/server-acl-init/rules.go index eb24b6138e..8b2dec7a14 100644 --- a/control-plane/subcommand/server-acl-init/rules.go +++ b/control-plane/subcommand/server-acl-init/rules.go @@ -8,6 +8,7 @@ import ( type rulesData struct { EnablePartitions bool + EnablePeering bool PartitionName string EnableNamespaces bool SyncConsulDestNS string @@ -315,6 +316,9 @@ partition "{{ .PartitionName }}" { {{- if .EnableNamespaces }} operator = "write" {{- end }} +{{- end }} +{{- if .EnablePeering }} + peering = "write" {{- end }} node_prefix "" { policy = "write" @@ -416,6 +420,7 @@ partition "{{ .PartitionName }}" { func (c *Command) rulesData() rulesData { return rulesData{ EnablePartitions: c.flagEnablePartitions, + EnablePeering: c.flagEnablePeering, PartitionName: c.flagPartitionName, EnableNamespaces: c.flagEnableNamespaces, SyncConsulDestNS: c.flagConsulSyncDestinationNamespace, diff --git a/control-plane/subcommand/server-acl-init/rules_test.go b/control-plane/subcommand/server-acl-init/rules_test.go index 723ab55f4e..1e736f9a95 100644 --- a/control-plane/subcommand/server-acl-init/rules_test.go +++ b/control-plane/subcommand/server-acl-init/rules_test.go @@ -848,12 +848,14 @@ func TestInjectRules(t *testing.T) { cases := []struct { EnableNamespaces bool EnablePartitions bool + EnablePeering bool PartitionName string Expected string }{ { EnableNamespaces: false, EnablePartitions: false, + EnablePeering: false, Expected: ` node_prefix "" { policy = "write" @@ -866,6 +868,7 @@ func TestInjectRules(t *testing.T) { { EnableNamespaces: true, EnablePartitions: false, + EnablePeering: false, Expected: ` operator = "write" node_prefix "" { @@ -877,13 +880,51 @@ func TestInjectRules(t *testing.T) { policy = "write" } }`, + }, + { + EnableNamespaces: true, + EnablePartitions: false, + EnablePeering: true, + Expected: ` + operator = "write" + peering = "write" + node_prefix "" { + policy = "write" + } + namespace_prefix "" { + acl = "write" + service_prefix "" { + policy = "write" + } + }`, + }, + { + EnableNamespaces: true, + EnablePartitions: true, + EnablePeering: false, + PartitionName: "part-1", + Expected: ` +partition "part-1" { + node_prefix "" { + policy = "write" + } + namespace_prefix "" { + policy = "write" + acl = "write" + service_prefix "" { + policy = "write" + } + } +}`, }, { EnableNamespaces: true, EnablePartitions: true, + EnablePeering: true, PartitionName: "part-1", Expected: ` partition "part-1" { + peering = "write" node_prefix "" { policy = "write" } @@ -899,13 +940,14 @@ partition "part-1" { } for _, tt := range cases { - caseName := fmt.Sprintf("ns=%t, partition=%t", tt.EnableNamespaces, tt.EnablePartitions) + caseName := fmt.Sprintf("ns=%t, partition=%t, peering=%t", tt.EnableNamespaces, tt.EnablePartitions, tt.EnablePeering) t.Run(caseName, func(t *testing.T) { cmd := Command{ flagEnablePartitions: tt.EnablePartitions, flagPartitionName: tt.PartitionName, flagEnableNamespaces: tt.EnableNamespaces, + flagEnablePeering: tt.EnablePeering, } injectorRules, err := cmd.injectRules() From 2cc47554e8c34a3d2e3839bca004c2cff2a5e557 Mon Sep 17 00:00:00 2001 From: DanStough Date: Tue, 19 Jul 2022 12:04:06 -0400 Subject: [PATCH 057/235] feat(crd): add destination to service-defaults --- CHANGELOG.md | 3 + acceptance/go.mod | 14 +-- acceptance/go.sum | 36 ++++--- .../consul/templates/crd-servicedefaults.yaml | 19 ++++ .../api/v1alpha1/servicedefaults_types.go | 80 ++++++++++++++++ .../v1alpha1/servicedefaults_types_test.go | 94 +++++++++++++++++++ .../api/v1alpha1/serviceintentions_types.go | 4 +- .../v1alpha1/serviceintentions_types_test.go | 62 ++++++------ .../serviceintentions_webhook_test.go | 40 ++++---- .../api/v1alpha1/zz_generated.deepcopy.go | 55 ++++++++--- .../consul.hashicorp.com_servicedefaults.yaml | 19 ++++ .../configentry_controller_ent_test.go | 6 +- .../controller/configentry_controller_test.go | 6 +- control-plane/go.mod | 20 ++-- control-plane/go.sum | 33 ++++--- 15 files changed, 365 insertions(+), 126 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9c1c8353f..6180e67d40 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## UNRELEASED +FEATURES: +* Transparent Proxy Egress + * Add support for Destinations on the Service Defaults CRD. [[GH-1352](https://github.com/hashicorp/consul-k8s/pull/1352)] FEATURES: * [Experimental] Cluster Peering: diff --git a/acceptance/go.mod b/acceptance/go.mod index 494fc214d1..1115a3a7a5 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -5,8 +5,8 @@ go 1.18 require ( github.com/gruntwork-io/terratest v0.31.2 github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638 - github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228 - github.com/hashicorp/consul/sdk v0.9.0 + github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df + github.com/hashicorp/consul/sdk v0.10.0 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.2.0 github.com/hashicorp/vault/api v1.2.0 @@ -19,7 +19,7 @@ require ( require ( cloud.google.com/go v0.54.0 // indirect - github.com/armon/go-metrics v0.3.9 // indirect + github.com/armon/go-metrics v0.3.10 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/aws/aws-sdk-go v1.30.27 // indirect github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect @@ -51,9 +51,9 @@ require ( github.com/hashicorp/go-secure-stdlib/parseutil v0.1.1 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.1 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect - github.com/hashicorp/golang-lru v0.5.3 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/serf v0.9.6 // indirect + github.com/hashicorp/serf v0.9.7 // indirect github.com/hashicorp/vault/sdk v0.2.1 // indirect github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -83,9 +83,9 @@ require ( github.com/urfave/cli v1.22.2 // indirect go.uber.org/atomic v1.7.0 // indirect golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect + golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect golang.org/x/text v0.3.6 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect diff --git a/acceptance/go.sum b/acceptance/go.sum index 7b40682c1e..f430da635a 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -82,8 +82,8 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= github.com/armon/go-metrics v0.3.3/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= -github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -324,11 +324,10 @@ github.com/gruntwork-io/terratest v0.31.2 h1:xvYHA80MUq5kx670dM18HInewOrrQrAN+Xb github.com/gruntwork-io/terratest v0.31.2/go.mod h1:EEgJie28gX/4AD71IFqgMj6e99KP5mi81hEtzmDjxTo= github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638 h1:z68s6H6O3RjxDmNvou/2/3UBrsJkrMcNzI0IQN5scAM= github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638/go.mod h1:7ZeaiADGbvJDuoWAT8UKj6KCcLsFUk+34OkUGMVtdXg= -github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228 h1:BqzKe5O+75uYcFfJI0mJz3rhCgdVztvEj3rEs4xpPr0= -github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= -github.com/hashicorp/consul/sdk v0.9.0 h1:NGSHAU7X3yDCjo8WBUbNOtD3BSqv8u0vu3+zNxgmxQI= -github.com/hashicorp/consul/sdk v0.9.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df h1:CCh336XUGPaMNqMkzRAeEL0BFin7LhX729xy3IxE5Y4= +github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI= +github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -349,6 +348,7 @@ github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjh github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= +github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= @@ -380,21 +380,20 @@ github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+d github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk= github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= -github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= -github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM= +github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/vault/api v1.0.5-0.20200519221902-385fac77e20f/go.mod h1:euTFbi2YJgwcju3imEt919lhJKF68nN1cQPq3aA+kBE= github.com/hashicorp/vault/api v1.2.0 h1:ysGFc6XRGbv05NsWPzuO5VTv68Lj8jtwATxRLFOpP9s= github.com/hashicorp/vault/api v1.2.0/go.mod h1:dAjw0T5shMnrfH7Q/Mst+LrcTKvStZBVs1PICEDpUqY= @@ -751,8 +750,8 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -807,7 +806,6 @@ golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -831,8 +829,8 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo= -golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= diff --git a/charts/consul/templates/crd-servicedefaults.yaml b/charts/consul/templates/crd-servicedefaults.yaml index 923aaf757b..ea7720e9a2 100644 --- a/charts/consul/templates/crd-servicedefaults.yaml +++ b/charts/consul/templates/crd-servicedefaults.yaml @@ -57,6 +57,25 @@ spec: spec: description: ServiceDefaultsSpec defines the desired state of ServiceDefaults. properties: + destination: + description: Destination is an address(es)/port combination that represents + an endpoint outside the mesh. This is only valid when the mesh is + configured in "transparent" mode. Destinations live outside of Consul's + catalog, and because of this, they do not require an artificial + node to be created. + properties: + addresses: + description: Addresses is a list of IPs and/or hostnames that + can be dialed and routed through a terminating gateway. + items: + type: string + type: array + port: + description: Port is the port that can be dialed on any of the + addresses in this Destination. + format: int32 + type: integer + type: object expose: description: Expose controls the default expose path configuration for Envoy. diff --git a/control-plane/api/v1alpha1/servicedefaults_types.go b/control-plane/api/v1alpha1/servicedefaults_types.go index f615f68616..41c855d75c 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types.go +++ b/control-plane/api/v1alpha1/servicedefaults_types.go @@ -1,15 +1,19 @@ package v1alpha1 import ( + "fmt" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/consul-k8s/control-plane/api/common" capi "github.com/hashicorp/consul/api" + "github.com/miekg/dns" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/validation/field" + "net" + "strings" ) const ( @@ -75,6 +79,11 @@ type ServiceDefaultsSpec struct { // and per-upstream configuration overrides. Note that per-upstream configuration applies // across all federated datacenters to the pairing of source and upstream destination services. UpstreamConfig *Upstreams `json:"upstreamConfig,omitempty"` + // Destination is an address(es)/port combination that represents an endpoint + // outside the mesh. This is only valid when the mesh is configured in "transparent" + // mode. Destinations live outside of Consul's catalog, and because of this, they + // do not require an artificial node to be created. + Destination *ServiceDefaultsDestination `json:"destination,omitempty"` } type Upstreams struct { @@ -150,6 +159,15 @@ type PassiveHealthCheck struct { MaxFailures uint32 `json:"maxFailures,omitempty"` } +type ServiceDefaultsDestination struct { + // Addresses is a list of IPs and/or hostnames that can be dialed + // and routed through a terminating gateway. + Addresses []string `json:"addresses,omitempty"` + // Port is the port that can be dialed on any of the addresses in this + // Destination. + Port uint32 `json:"port,omitempty"` +} + func (in *ServiceDefaults) ConsulKind() string { return capi.ServiceDefaults } @@ -235,6 +253,7 @@ func (in *ServiceDefaults) ToConsul(datacenter string) capi.ConfigEntry { ExternalSNI: in.Spec.ExternalSNI, TransparentProxy: in.Spec.TransparentProxy.toConsul(), UpstreamConfig: in.Spec.UpstreamConfig.toConsul(), + Destination: in.Spec.Destination.toConsul(), Meta: meta(datacenter), } } @@ -258,6 +277,9 @@ func (in *ServiceDefaults) Validate(consulMeta common.ConsulMeta) error { if err := in.Spec.Mode.validate(path.Child("mode")); err != nil { allErrs = append(allErrs, err) } + if err := in.Spec.Destination.validate(path.Child("destination")); err != nil { + allErrs = append(allErrs, err...) + } allErrs = append(allErrs, in.Spec.UpstreamConfig.validate(path.Child("upstreamConfig"), consulMeta.PartitionsEnabled)...) allErrs = append(allErrs, in.Spec.Expose.validate(path.Child("expose"))...) @@ -361,6 +383,64 @@ func (in *PassiveHealthCheck) toConsul() *capi.PassiveHealthCheck { } } +func (in *ServiceDefaultsDestination) validate(path *field.Path) field.ErrorList { + if in == nil { + return nil + } + + var errs field.ErrorList + + if len(in.Addresses) == 0 { + errs = append(errs, field.Required(path.Child("addresses"), "at least one address must be define per destination")) + } + + seen := make(map[string]bool, len(in.Addresses)) + for idx, address := range in.Addresses { + if _, ok := seen[address]; ok { + errs = append(errs, field.Duplicate(path.Child("addresses").Index(idx), address)) + continue + } + seen[address] = true + + if !validEndpointAddress(address) { + errs = append(errs, field.Invalid(path.Child("addresses").Index(idx), address, fmt.Sprintf("address %s is not a valid IP or hostname", address))) + } + } + + if in.Port < 1 || in.Port > 65535 { + errs = append(errs, field.Invalid(path.Child("port"), in.Port, "invalid port number")) + } + + return errs +} + +func validEndpointAddress(address string) bool { + var valid bool + + if address == "" { + return false + } + + ip := net.ParseIP(address) + valid = ip != nil + + hasWildcard := strings.Contains(address, "*") + _, ok := dns.IsDomainName(address) + valid = valid || (ok && !hasWildcard) + + return valid +} + +func (in *ServiceDefaultsDestination) toConsul() *capi.DestinationConfig { + if in == nil { + return nil + } + return &capi.DestinationConfig{ + Addresses: in.Addresses, + Port: int(in.Port), + } +} + // DefaultNamespaceFields has no behaviour here as service-defaults have no namespace specific fields. func (in *ServiceDefaults) DefaultNamespaceFields(_ common.ConsulMeta) { } diff --git a/control-plane/api/v1alpha1/servicedefaults_types_test.go b/control-plane/api/v1alpha1/servicedefaults_types_test.go index 8042a5b2b3..a19ea556b3 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types_test.go +++ b/control-plane/api/v1alpha1/servicedefaults_types_test.go @@ -137,6 +137,10 @@ func TestServiceDefaults_ToConsul(t *testing.T) { }, }, }, + Destination: &ServiceDefaultsDestination{ + Addresses: []string{"api.google.com"}, + Port: 443, + }, }, }, &capi.ServiceConfigEntry{ @@ -235,6 +239,10 @@ func TestServiceDefaults_ToConsul(t *testing.T) { }, }, }, + Destination: &capi.DestinationConfig{ + Addresses: []string{"api.google.com"}, + Port: 443, + }, Meta: map[string]string{ common.SourceKey: common.SourceValue, common.DatacenterKey: "datacenter", @@ -378,6 +386,10 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { }, }, }, + Destination: &ServiceDefaultsDestination{ + Addresses: []string{"api.google.com"}, + Port: 443, + }, }, }, &capi.ServiceConfigEntry{ @@ -472,6 +484,10 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { }, }, }, + Destination: &capi.DestinationConfig{ + Addresses: []string{"api.google.com"}, + Port: 443, + }, }, true, }, @@ -589,6 +605,20 @@ func TestServiceDefaults_Validate(t *testing.T) { }, expectedErrMsg: "", }, + "valid - destination": { + input: &ServiceDefaults{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-service", + }, + Spec: ServiceDefaultsSpec{ + Destination: &ServiceDefaultsDestination{ + Addresses: []string{"www.google.com"}, + Port: 443, + }, + }, + }, + expectedErrMsg: "", + }, "protocol": { input: &ServiceDefaults{ ObjectMeta: metav1.ObjectMeta{ @@ -802,6 +832,70 @@ func TestServiceDefaults_Validate(t *testing.T) { }, expectedErrMsg: "servicedefaults.consul.hashicorp.com \"my-service\" is invalid: [spec.protocol: Invalid value: \"invalid\": must be one of \"tcp\", \"http\", \"http2\", \"grpc\", spec.meshGateway.mode: Invalid value: \"invalid-mode\": must be one of \"remote\", \"local\", \"none\", \"\", spec.transparentProxy.outboundListenerPort: Invalid value: 1000: use the annotation `consul.hashicorp.com/transparent-proxy-outbound-listener-port` to configure the Outbound Listener Port, spec.mode: Invalid value: \"transparent\": use the annotation `consul.hashicorp.com/transparent-proxy` to configure the Transparent Proxy Mode, spec.expose.paths[0].path: Invalid value: \"invalid-path\": must begin with a '/', spec.expose.paths[0].protocol: Invalid value: \"invalid-protocol\": must be one of \"http\", \"http2\"]", }, + "destination.addresses (missing)": { + input: &ServiceDefaults{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-service", + }, + Spec: ServiceDefaultsSpec{ + Destination: &ServiceDefaultsDestination{ + Addresses: []string{}, + Port: 443, + }, + }, + }, + expectedErrMsg: `servicedefaults.consul.hashicorp.com "my-service" is invalid: spec.destination.addresses: Required value: at least one address must be define per destination`, + }, + "destination.addresses (duplicate)": { + input: &ServiceDefaults{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-service", + }, + Spec: ServiceDefaultsSpec{ + Destination: &ServiceDefaultsDestination{ + Addresses: []string{ + "google.com", + "google.com", + }, + Port: 443, + }, + }, + }, + expectedErrMsg: `servicedefaults.consul.hashicorp.com "my-service" is invalid: spec.destination.addresses[1]: Duplicate value: "google.com"`, + }, + "destination.addresses (invalid)": { + input: &ServiceDefaults{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-service", + }, + Spec: ServiceDefaultsSpec{ + Destination: &ServiceDefaultsDestination{ + Addresses: []string{ + "...", + "", + "*.google.com", + }, + Port: 443, + }, + }, + }, + expectedErrMsg: `servicedefaults.consul.hashicorp.com "my-service" is invalid: [spec.destination.addresses[0]: Invalid value: "...": address ... is not a valid IP or hostname, spec.destination.addresses[1]: Invalid value: "": address is not a valid IP or hostname, spec.destination.addresses[2]: Invalid value: "*.google.com": address *.google.com is not a valid IP or hostname]`, + }, + "destination.port": { + input: &ServiceDefaults{ + ObjectMeta: metav1.ObjectMeta{ + Name: "my-service", + }, + Spec: ServiceDefaultsSpec{ + Destination: &ServiceDefaultsDestination{ + Addresses: []string{ + "google.com", + }, + }, + }, + }, + expectedErrMsg: `servicedefaults.consul.hashicorp.com "my-service" is invalid: spec.destination.port: Invalid value: 0x0: invalid port number`, + }, } for name, testCase := range cases { diff --git a/control-plane/api/v1alpha1/serviceintentions_types.go b/control-plane/api/v1alpha1/serviceintentions_types.go index b2e5cf4872..6488a3615c 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types.go +++ b/control-plane/api/v1alpha1/serviceintentions_types.go @@ -50,14 +50,14 @@ type ServiceIntentionsList struct { // ServiceIntentionsSpec defines the desired state of ServiceIntentions. type ServiceIntentionsSpec struct { // Destination is the intention destination that will have the authorization granted to. - Destination Destination `json:"destination,omitempty"` + Destination IntentionDestination `json:"destination,omitempty"` // Sources is the list of all intention sources and the authorization granted to those sources. // The order of this list does not matter, but out of convenience Consul will always store this // reverse sorted by intention precedence, as that is the order that they will be evaluated at enforcement time. Sources SourceIntentions `json:"sources,omitempty"` } -type Destination struct { +type IntentionDestination struct { // Name is the destination of all intentions defined in this config entry. // This may be set to the wildcard character (*) to match // all services that don't otherwise have intentions defined. diff --git a/control-plane/api/v1alpha1/serviceintentions_types_test.go b/control-plane/api/v1alpha1/serviceintentions_types_test.go index ee79fe8c99..f9be4120f2 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types_test.go +++ b/control-plane/api/v1alpha1/serviceintentions_types_test.go @@ -43,7 +43,7 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { Name: "name", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "svc-name", Namespace: "test", }, @@ -175,7 +175,7 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { Name: "name", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "bar", }, Sources: SourceIntentions{ @@ -247,7 +247,7 @@ func TestServiceIntentions_ToConsul(t *testing.T) { Name: "name", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "svc-name", Namespace: "dest-ns", }, @@ -455,7 +455,7 @@ func TestServiceIntentions_ConsulName(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "baz", }, @@ -470,7 +470,7 @@ func TestServiceIntentions_KubernetesName(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "baz", }, @@ -485,7 +485,7 @@ func TestServiceIntentions_ConsulNamespace(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "baz", }, @@ -504,7 +504,7 @@ func TestServiceIntentions_ConsulNamespaceWithWildcard(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "*", }, @@ -575,7 +575,7 @@ func TestServiceIntentions_DefaultNamespaceFields(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "bar", }, }, @@ -586,7 +586,7 @@ func TestServiceIntentions_DefaultNamespaceFields(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "bar", Namespace: s.expectedDestination, }, @@ -611,7 +611,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -666,7 +666,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -718,7 +718,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", }, Sources: SourceIntentions{ @@ -766,7 +766,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -784,7 +784,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -808,7 +808,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -839,7 +839,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -871,7 +871,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -903,7 +903,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -935,7 +935,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -966,7 +966,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -1003,7 +1003,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -1064,7 +1064,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -1095,7 +1095,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace", }, @@ -1127,7 +1127,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace-a", }, @@ -1150,7 +1150,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", }, Sources: SourceIntentions{ @@ -1173,7 +1173,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", }, Sources: SourceIntentions{ @@ -1207,7 +1207,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace-a", }, @@ -1243,7 +1243,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace-a", }, @@ -1278,7 +1278,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace-a", }, @@ -1317,7 +1317,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace-a", }, @@ -1349,7 +1349,7 @@ func TestServiceIntentions_Validate(t *testing.T) { Name: "does-not-matter", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "dest-service", Namespace: "namespace-a", }, diff --git a/control-plane/api/v1alpha1/serviceintentions_webhook_test.go b/control-plane/api/v1alpha1/serviceintentions_webhook_test.go index 8c1ba98fd7..17b1881c5a 100644 --- a/control-plane/api/v1alpha1/serviceintentions_webhook_test.go +++ b/control-plane/api/v1alpha1/serviceintentions_webhook_test.go @@ -34,7 +34,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -57,7 +57,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -80,7 +80,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -98,7 +98,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "bar-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -121,7 +121,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -139,7 +139,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "bar-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "baz", }, @@ -162,7 +162,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -180,7 +180,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "bar-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "baz", }, @@ -203,7 +203,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", }, Sources: SourceIntentions{ @@ -220,7 +220,7 @@ func TestHandle_ServiceIntentions_Create(t *testing.T) { Name: "bar-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", }, Sources: SourceIntentions{ @@ -293,7 +293,7 @@ func TestHandle_ServiceIntentions_Update(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -316,7 +316,7 @@ func TestHandle_ServiceIntentions_Update(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -338,7 +338,7 @@ func TestHandle_ServiceIntentions_Update(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -361,7 +361,7 @@ func TestHandle_ServiceIntentions_Update(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo-bar", Namespace: "bar", }, @@ -384,7 +384,7 @@ func TestHandle_ServiceIntentions_Update(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -407,7 +407,7 @@ func TestHandle_ServiceIntentions_Update(t *testing.T) { Name: "foo-intention", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar-foo", }, @@ -488,7 +488,7 @@ func TestHandle_ServiceIntentions_Patches(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, @@ -511,7 +511,7 @@ func TestHandle_ServiceIntentions_Patches(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", }, Sources: SourceIntentions{ @@ -539,7 +539,7 @@ func TestHandle_ServiceIntentions_Patches(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", }, Sources: SourceIntentions{ @@ -566,7 +566,7 @@ func TestHandle_ServiceIntentions_Patches(t *testing.T) { Namespace: "bar", }, Spec: ServiceIntentionsSpec{ - Destination: Destination{ + Destination: IntentionDestination{ Name: "foo", Namespace: "bar", }, diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index 437ca89d1c..85d64c3c85 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -63,21 +63,6 @@ func (in *CookieConfig) DeepCopy() *CookieConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Destination) DeepCopyInto(out *Destination) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Destination. -func (in *Destination) DeepCopy() *Destination { - if in == nil { - return nil - } - out := new(Destination) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ExportedService) DeepCopyInto(out *ExportedService) { *out = *in @@ -472,6 +457,21 @@ func (in *IngressService) DeepCopy() *IngressService { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IntentionDestination) DeepCopyInto(out *IntentionDestination) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IntentionDestination. +func (in *IntentionDestination) DeepCopy() *IntentionDestination { + if in == nil { + return nil + } + out := new(IntentionDestination) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IntentionHTTPHeaderPermission) DeepCopyInto(out *IntentionHTTPHeaderPermission) { *out = *in @@ -1243,6 +1243,26 @@ func (in *ServiceDefaults) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceDefaultsDestination) DeepCopyInto(out *ServiceDefaultsDestination) { + *out = *in + if in.Addresses != nil { + in, out := &in.Addresses, &out.Addresses + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceDefaultsDestination. +func (in *ServiceDefaultsDestination) DeepCopy() *ServiceDefaultsDestination { + if in == nil { + return nil + } + out := new(ServiceDefaultsDestination) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceDefaultsList) DeepCopyInto(out *ServiceDefaultsList) { *out = *in @@ -1295,6 +1315,11 @@ func (in *ServiceDefaultsSpec) DeepCopyInto(out *ServiceDefaultsSpec) { *out = new(Upstreams) (*in).DeepCopyInto(*out) } + if in.Destination != nil { + in, out := &in.Destination, &out.Destination + *out = new(ServiceDefaultsDestination) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceDefaultsSpec. diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml index e0fff822e9..f536c17bed 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml @@ -50,6 +50,25 @@ spec: spec: description: ServiceDefaultsSpec defines the desired state of ServiceDefaults. properties: + destination: + description: Destination is an address(es)/port combination that represents + an endpoint outside the mesh. This is only valid when the mesh is + configured in "transparent" mode. Destinations live outside of Consul's + catalog, and because of this, they do not require an artificial + node to be created. + properties: + addresses: + description: Addresses is a list of IPs and/or hostnames that + can be dialed and routed through a terminating gateway. + items: + type: string + type: array + port: + description: Port is the port that can be dialed on any of the + addresses in this Destination. + format: int32 + type: integer + type: object expose: description: Expose controls the default expose path configuration for Envoy. diff --git a/control-plane/controller/configentry_controller_ent_test.go b/control-plane/controller/configentry_controller_ent_test.go index 11bdaa33bb..7b40947df5 100644 --- a/control-plane/controller/configentry_controller_ent_test.go +++ b/control-plane/controller/configentry_controller_ent_test.go @@ -154,7 +154,7 @@ func TestConfigEntryController_createsConfigEntry_consulNamespaces(tt *testing.T Namespace: c.SourceKubeNS, }, Spec: v1alpha1.ServiceIntentionsSpec{ - Destination: v1alpha1.Destination{ + Destination: v1alpha1.IntentionDestination{ Name: "test", Namespace: c.ExpConsulNS, }, @@ -402,7 +402,7 @@ func TestConfigEntryController_updatesConfigEntry_consulNamespaces(tt *testing.T Finalizers: []string{controller.FinalizerName}, }, Spec: v1alpha1.ServiceIntentionsSpec{ - Destination: v1alpha1.Destination{ + Destination: v1alpha1.IntentionDestination{ Name: "foo", Namespace: c.ExpConsulNS, }, @@ -667,7 +667,7 @@ func TestConfigEntryController_deletesConfigEntry_consulNamespaces(tt *testing.T DeletionTimestamp: &metav1.Time{Time: time.Now()}, }, Spec: v1alpha1.ServiceIntentionsSpec{ - Destination: v1alpha1.Destination{ + Destination: v1alpha1.IntentionDestination{ Name: "test", Namespace: c.ExpConsulNS, }, diff --git a/control-plane/controller/configentry_controller_test.go b/control-plane/controller/configentry_controller_test.go index 74787beb12..5b92feedd5 100644 --- a/control-plane/controller/configentry_controller_test.go +++ b/control-plane/controller/configentry_controller_test.go @@ -268,7 +268,7 @@ func TestConfigEntryControllers_createsConfigEntry(t *testing.T) { Namespace: kubeNS, }, Spec: v1alpha1.ServiceIntentionsSpec{ - Destination: v1alpha1.Destination{ + Destination: v1alpha1.IntentionDestination{ Name: "foo", }, Sources: v1alpha1.SourceIntentions{ @@ -738,7 +738,7 @@ func TestConfigEntryControllers_updatesConfigEntry(t *testing.T) { Namespace: kubeNS, }, Spec: v1alpha1.ServiceIntentionsSpec{ - Destination: v1alpha1.Destination{ + Destination: v1alpha1.IntentionDestination{ Name: "foo", }, Sources: v1alpha1.SourceIntentions{ @@ -1169,7 +1169,7 @@ func TestConfigEntryControllers_deletesConfigEntry(t *testing.T) { Finalizers: []string{FinalizerName}, }, Spec: v1alpha1.ServiceIntentionsSpec{ - Destination: v1alpha1.Destination{ + Destination: v1alpha1.IntentionDestination{ Name: "foo", }, Sources: v1alpha1.SourceIntentions{ diff --git a/control-plane/go.mod b/control-plane/go.mod index f95b55638c..fe3ddc7c84 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -6,18 +6,20 @@ require ( github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228 - github.com/hashicorp/consul/sdk v0.9.0 + github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df + github.com/hashicorp/consul/sdk v0.10.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f github.com/hashicorp/go-hclog v0.16.1 - github.com/hashicorp/go-multierror v1.1.0 - github.com/hashicorp/serf v0.9.6 + github.com/hashicorp/go-multierror v1.1.1 + github.com/hashicorp/serf v0.9.7 github.com/kr/text v0.2.0 + github.com/miekg/dns v1.1.41 github.com/mitchellh/cli v1.1.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.4.1 github.com/stretchr/testify v1.7.0 go.uber.org/zap v1.19.0 + golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac gomodules.xyz/jsonpatch/v2 v2.2.0 k8s.io/api v0.22.2 @@ -40,7 +42,7 @@ require ( github.com/Azure/go-autorest/autorest/validation v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/armon/go-metrics v0.3.9 // indirect + github.com/armon/go-metrics v0.3.10 // indirect github.com/armon/go-radix v1.0.0 // indirect github.com/aws/aws-sdk-go v1.25.41 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -67,11 +69,9 @@ require ( github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.0 // indirect - github.com/hashicorp/go-msgpack v0.5.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/go-uuid v1.0.2 // indirect - github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/mdns v1.0.4 // indirect github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -82,7 +82,6 @@ require ( github.com/mattn/go-colorable v0.1.8 // indirect github.com/mattn/go-isatty v0.0.13 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/miekg/dns v1.1.41 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 // indirect @@ -105,12 +104,11 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect + golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect - golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/api v0.20.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/control-plane/go.sum b/control-plane/go.sum index 728ae24d43..83919ba09e 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -81,8 +81,8 @@ github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kd github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= -github.com/armon/go-metrics v0.3.9 h1:O2sNqxBdvq8Eq5xmzljcYzAORli6RWCvEym4cJf9m18= -github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= +github.com/armon/go-metrics v0.3.10 h1:FR+drcQStOe+32sYyJYyZ7FIdgoGGBnwLl+flodp8Uo= +github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= @@ -296,12 +296,11 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228 h1:BqzKe5O+75uYcFfJI0mJz3rhCgdVztvEj3rEs4xpPr0= -github.com/hashicorp/consul/api v1.10.1-0.20220614213650-6453375ab228/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ= +github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df h1:CCh336XUGPaMNqMkzRAeEL0BFin7LhX729xy3IxE5Y4= +github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50 h1:GwbRRT+QxMRbYI608FGwTfcZ0iOVLX69B2ePjpQoyXw= -github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= -github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= +github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI= +github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -311,6 +310,7 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f h1:7WFMVeuJQp6BkzuTv9O52pzwtEFVUJubKYN+zez8eTI= github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f/go.mod h1:D4eo8/CN92vm9/9UDG+ldX1/fMFa4kpl8qzyTolus8o= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o= github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -320,8 +320,9 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI= github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= @@ -336,8 +337,9 @@ github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2I github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= @@ -345,11 +347,12 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.3.0 h1:8+567mCcFDnS5ADl7lrpxPMWiFCElyUEeW0gtj34fMA= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM= +github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.6 h1:uuEX1kLR6aoda1TBttmJQKDLZE1Ob7KN0NPdE7EtCDc= -github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY= +github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -393,6 +396,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -718,8 +722,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= +golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -772,7 +776,6 @@ golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= From f6ecf082ca168529afa1ac53e6665fa6b32d58dc Mon Sep 17 00:00:00 2001 From: DanStough Date: Mon, 18 Jul 2022 23:01:31 -0400 Subject: [PATCH 058/235] update to use gox for dev builds --- CONTRIBUTING.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f4ea447aaf..c9107cf11e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,11 @@ You will also need to install the Docker engine: - [Docker for Mac](https://docs.docker.com/engine/installation/mac/) - [Docker for Windows](https://docs.docker.com/engine/installation/windows/) - [Docker for Linux](https://docs.docker.com/engine/installation/linux/ubuntulinux/) + +Install [gox](https://github.com/mitchellh/gox) (v1.14+). For Mac and Linux: + ```bash + brew install gox + ``` Clone the repository: From d3b38de9e9cdb9b07c8ddfb2861e41af9e3a9d32 Mon Sep 17 00:00:00 2001 From: DanStough Date: Tue, 19 Jul 2022 12:39:45 -0400 Subject: [PATCH 059/235] ignore vscode --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 8014afb2bf..20ab4d997b 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ values.dev.yaml bin/ pkg/ .idea/ +.vscode From f1581c457b40b3ae20c94a1a484a5e36ca33395c Mon Sep 17 00:00:00 2001 From: Evan Culver Date: Thu, 28 Jul 2022 14:08:15 -0400 Subject: [PATCH 060/235] Bump default Envoy version to 1.23.0 (#1377) Signed-off-by: Evan Culver --- CHANGELOG.md | 3 +++ charts/consul/Chart.yaml | 2 +- charts/consul/values.yaml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6180e67d40..758365a555 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ FEATURES: * Transparent Proxy Egress * Add support for Destinations on the Service Defaults CRD. [[GH-1352](https://github.com/hashicorp/consul-k8s/pull/1352)] +IMPROVEMENTS: +* Helm + * Bump default Envoy version to 1.23.0. [[GH-1377](https://github.com/hashicorp/consul-k8s/pull/1377)] FEATURES: * [Experimental] Cluster Peering: * Add support for ACLs and TLS. [[GH-1343](https://github.com/hashicorp/consul-k8s/pull/1343)] [[GH-1366](https://github.com/hashicorp/consul-k8s/pull/1366)] diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 527f5128eb..faede92331 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -17,7 +17,7 @@ annotations: - name: consul-k8s-control-plane image: hashicorp/consul-k8s-control-plane:0.46.1 - name: envoy - image: envoyproxy/envoy:v1.22.2 + image: envoyproxy/envoy:v1.23.0 artifacthub.io/license: MPL-2.0 artifacthub.io/links: | - name: Documentation diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 44e274c58d..a87644a8a0 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -613,7 +613,7 @@ global: # connect-injected sidecar proxies and mesh, terminating, and ingress gateways. # See https://www.consul.io/docs/connect/proxies/envoy for full compatibility matrix between Consul and Envoy. # @default: envoyproxy/envoy-alpine: - imageEnvoy: "envoyproxy/envoy:v1.22.2" + imageEnvoy: "envoyproxy/envoy:v1.23.0" # Configuration for running this Helm chart on the Red Hat OpenShift platform. # This Helm chart currently supports OpenShift v4.x+. From 5f53ba063931c28ce07d519612c9976169d474ef Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Fri, 29 Jul 2022 15:03:42 -0600 Subject: [PATCH 061/235] Increase ELB propagation wait time (#1385) --- hack/aws-acceptance-test-cleanup/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/aws-acceptance-test-cleanup/main.go b/hack/aws-acceptance-test-cleanup/main.go index 3c121dfa11..d5932d8978 100644 --- a/hack/aws-acceptance-test-cleanup/main.go +++ b/hack/aws-acceptance-test-cleanup/main.go @@ -364,7 +364,7 @@ func realMain(ctx context.Context) error { return err } // Allow time for ELB deletion to propagate so that we can detach the internet gateway. - time.Sleep(10 * time.Second) + time.Sleep(30 * time.Second) fmt.Printf("ELB: Destroyed [id=%s]\n", *elbDescrip.LoadBalancerName) } From d04904f8ab1f513acc7415516cf9e8258e83cf4a Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Mon, 1 Aug 2022 16:05:46 -0700 Subject: [PATCH 062/235] peering: expose servers over Kubernetes service (#1378) - Add new expose-servers service to Helm chart - Support scraping addresses from expose-servers service when type LB or Nodeport and using those to generate the token - Bump consul/api module to use generate token endpoint changes from Update generate token endpoint to take external addresses consul#13844 - Update acceptance tests to deploy 3 servers, and on clouds it'll use a load balancer service, on kind itll use a nodeport service. --- .circleci/config.yml | 2 +- acceptance/framework/consul/helm_cluster.go | 1 - .../framework/consul/helm_cluster_test.go | 1 - acceptance/framework/k8s/deploy.go | 2 +- .../partitions/partitions_connect_test.go | 1 + .../peering_connect_namespaces_test.go | 18 +- .../tests/peering/peering_connect_test.go | 18 +- .../tests/vault/vault_partitions_test.go | 1 + .../templates/connect-inject-clusterrole.yaml | 2 +- .../templates/connect-inject-deployment.yaml | 9 +- .../templates/expose-servers-service.yaml | 63 ++++ .../test/unit/connect-inject-deployment.bats | 64 ++++ .../test/unit/expose-servers-service.bats | 265 ++++++++++++++++ charts/consul/values.yaml | 49 +++ .../peering_acceptor_controller.go | 97 +++++- .../peering_acceptor_controller_test.go | 298 ++++++++++++++++++ control-plane/go.mod | 2 +- control-plane/go.sum | 6 +- .../subcommand/inject-connect/command.go | 18 +- 19 files changed, 893 insertions(+), 24 deletions(-) create mode 100644 charts/consul/templates/expose-servers-service.yaml create mode 100644 charts/consul/test/unit/expose-servers-service.bats diff --git a/.circleci/config.yml b/.circleci/config.yml index b1bcce48c7..88649ec789 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -706,7 +706,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -disable-peering -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy - store_test_results: path: /tmp/test-results diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index bcd07ecf39..8a41f994e5 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -510,7 +510,6 @@ func configureSCCs(t *testing.T, client kubernetes.Interface, cfg *config.TestCo func defaultValues() map[string]string { values := map[string]string{ "server.replicas": "1", - "server.bootstrapExpect": "1", "connectInject.envoyExtraArgs": "--log-level debug", "connectInject.logLevel": "debug", // Disable DNS since enabling it changes the policy for the anonymous token, diff --git a/acceptance/framework/consul/helm_cluster_test.go b/acceptance/framework/consul/helm_cluster_test.go index 3fb6710c8b..552aed065c 100644 --- a/acceptance/framework/consul/helm_cluster_test.go +++ b/acceptance/framework/consul/helm_cluster_test.go @@ -24,7 +24,6 @@ func TestNewHelmCluster(t *testing.T) { helmValues: map[string]string{}, want: map[string]string{ "global.image": "test-config-image", - "server.bootstrapExpect": "1", "server.replicas": "1", "connectInject.envoyExtraArgs": "--log-level debug", "connectInject.logLevel": "debug", diff --git a/acceptance/framework/k8s/deploy.go b/acceptance/framework/k8s/deploy.go index 09272d5382..2a258dcd96 100644 --- a/acceptance/framework/k8s/deploy.go +++ b/acceptance/framework/k8s/deploy.go @@ -96,7 +96,7 @@ func CheckStaticServerConnectionMultipleFailureMessages(t *testing.T, options *k expectedOutput = expectedSuccessOutput } - retrier := &retry.Timer{Timeout: 80 * time.Second, Wait: 2 * time.Second} + retrier := &retry.Timer{Timeout: 160 * time.Second, Wait: 2 * time.Second} args := []string{"exec", "deploy/" + sourceApp, "-c", sourceApp, "--", "curl", "-vvvsSf"} args = append(args, curlArgs...) diff --git a/acceptance/tests/partitions/partitions_connect_test.go b/acceptance/tests/partitions/partitions_connect_test.go index d57e1af44a..e1a43850d6 100644 --- a/acceptance/tests/partitions/partitions_connect_test.go +++ b/acceptance/tests/partitions/partitions_connect_test.go @@ -123,6 +123,7 @@ func TestPartitions_Connect(t *testing.T) { serverHelmValues["global.adminPartitions.service.nodePort.https"] = "30000" serverHelmValues["meshGateway.service.type"] = "NodePort" serverHelmValues["meshGateway.service.nodePort"] = "30100" + serverHelmValues["server.exposeService.type"] = "NodePort" } releaseName := helpers.RandomName() diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index 78a1c58436..9ac02229a6 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" "testing" + "time" terratestk8s "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/consul" @@ -95,7 +96,7 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.peering.enabled": "true", "global.enableConsulNamespaces": "true", - "global.image": "thisisnotashwin/consul@sha256:b1d3f59406adf5fb9a3bee4ded058e619d3a186e83b2e2dc14d6da3f28a7073d", + "global.image": "ndhanushkodi/consul-dev:ent-backoff-fix", "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -122,6 +123,10 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.datacenter": staticServerPeer, } + if !cfg.UseKind { + staticServerPeerHelmValues["server.replicas"] = "3" + } + // On Kind, there are no load balancers but since all clusters // share the same node network (docker bridge), we can use // a NodePort service so that we can access node(s) in a different Kind cluster. @@ -129,6 +134,8 @@ func TestPeering_ConnectNamespaces(t *testing.T) { staticServerPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" staticServerPeerHelmValues["meshGateway.service.type"] = "NodePort" staticServerPeerHelmValues["meshGateway.service.nodePort"] = "30100" + staticServerPeerHelmValues["server.exposeService.type"] = "NodePort" + staticServerPeerHelmValues["server.exposeService.nodePort.grpc"] = "30200" } releaseName := helpers.RandomName() @@ -143,10 +150,16 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.datacenter": staticClientPeer, } + if !cfg.UseKind { + staticClientPeerHelmValues["server.replicas"] = "3" + } + if cfg.UseKind { staticClientPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" staticClientPeerHelmValues["meshGateway.service.type"] = "NodePort" staticClientPeerHelmValues["meshGateway.service.nodePort"] = "30100" + staticClientPeerHelmValues["server.exposeService.type"] = "NodePort" + staticClientPeerHelmValues["server.exposeService.nodePort.grpc"] = "30200" } helpers.MergeMaps(staticClientPeerHelmValues, commonHelmValues) @@ -162,7 +175,8 @@ func TestPeering_ConnectNamespaces(t *testing.T) { }) // Ensure the secret is created. - retry.Run(t, func(r *retry.R) { + timer := &retry.Timer{Timeout: 1 * time.Minute, Wait: 1 * time.Second} + retry.RunWith(timer, t, func(r *retry.R) { acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") require.NoError(r, err) require.NotEmpty(r, acceptorSecretResourceVersion) diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index d18d6bee70..d236c74e37 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" "testing" + "time" terratestk8s "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/consul" @@ -54,7 +55,7 @@ func TestPeering_Connect(t *testing.T) { commonHelmValues := map[string]string{ "global.peering.enabled": "true", - "global.image": "thisisnotashwin/consul@sha256:b1d3f59406adf5fb9a3bee4ded058e619d3a186e83b2e2dc14d6da3f28a7073d", + "global.image": "ndhanushkodi/consul-dev:ent-backoff-fix", "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -77,6 +78,10 @@ func TestPeering_Connect(t *testing.T) { "global.datacenter": staticServerPeer, } + if !cfg.UseKind { + staticServerPeerHelmValues["server.replicas"] = "3" + } + // On Kind, there are no load balancers but since all clusters // share the same node network (docker bridge), we can use // a NodePort service so that we can access node(s) in a different Kind cluster. @@ -84,6 +89,8 @@ func TestPeering_Connect(t *testing.T) { staticServerPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" staticServerPeerHelmValues["meshGateway.service.type"] = "NodePort" staticServerPeerHelmValues["meshGateway.service.nodePort"] = "30100" + staticServerPeerHelmValues["server.exposeService.type"] = "NodePort" + staticServerPeerHelmValues["server.exposeService.nodePort.grpc"] = "30200" } releaseName := helpers.RandomName() @@ -98,10 +105,16 @@ func TestPeering_Connect(t *testing.T) { "global.datacenter": staticClientPeer, } + if !cfg.UseKind { + staticServerPeerHelmValues["server.replicas"] = "3" + } + if cfg.UseKind { staticClientPeerHelmValues["server.exposeGossipAndRPCPorts"] = "true" staticClientPeerHelmValues["meshGateway.service.type"] = "NodePort" staticClientPeerHelmValues["meshGateway.service.nodePort"] = "30100" + staticClientPeerHelmValues["server.exposeService.type"] = "NodePort" + staticClientPeerHelmValues["server.exposeService.nodePort.grpc"] = "30200" } helpers.MergeMaps(staticClientPeerHelmValues, commonHelmValues) @@ -117,7 +130,8 @@ func TestPeering_Connect(t *testing.T) { }) // Ensure the secret is created. - retry.Run(t, func(r *retry.R) { + timer := &retry.Timer{Timeout: 1 * time.Minute, Wait: 1 * time.Second} + retry.RunWith(timer, t, func(r *retry.R) { acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") require.NoError(r, err) require.NotEmpty(r, acceptorSecretResourceVersion) diff --git a/acceptance/tests/vault/vault_partitions_test.go b/acceptance/tests/vault/vault_partitions_test.go index 19798a374d..31eac7bc1a 100644 --- a/acceptance/tests/vault/vault_partitions_test.go +++ b/acceptance/tests/vault/vault_partitions_test.go @@ -338,6 +338,7 @@ func TestVault_Partitions(t *testing.T) { serverHelmValues["global.adminPartitions.service.nodePort.https"] = "30000" serverHelmValues["meshGateway.service.type"] = "NodePort" serverHelmValues["meshGateway.service.nodePort"] = "30100" + serverHelmValues["server.exposeService.type"] = "NodePort" } helpers.MergeMaps(serverHelmValues, commonHelmValues) diff --git a/charts/consul/templates/connect-inject-clusterrole.yaml b/charts/consul/templates/connect-inject-clusterrole.yaml index 88194f4a61..846e70132a 100644 --- a/charts/consul/templates/connect-inject-clusterrole.yaml +++ b/charts/consul/templates/connect-inject-clusterrole.yaml @@ -19,7 +19,7 @@ rules: - get {{- end }} - apiGroups: [ "" ] - resources: [ "pods", "endpoints", "services", "namespaces" ] + resources: [ "pods", "endpoints", "services", "namespaces", "nodes" ] verbs: - "get" - "list" diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 134ecbd344..6cf1f27a90 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -11,6 +11,8 @@ {{- if .Values.global.lifecycleSidecarContainer }}{{ fail "global.lifecycleSidecarContainer has been renamed to global.consulSidecarContainer. Please set values using global.consulSidecarContainer." }}{{ end }} {{ template "consul.validateVaultWebhookCertConfiguration" . }} {{- template "consul.reservedNamesFailer" (list .Values.connectInject.consulNamespaces.consulDestinationNamespace "connectInject.consulNamespaces.consulDestinationNamespace") }} +{{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}} +{{- $serverExposeServiceEnabled := (or (and (ne (.Values.server.exposeService.enabled | toString) "-") .Values.server.exposeService.enabled) (and (eq (.Values.server.exposeService.enabled | toString) "-") (or .Values.global.peering.enabled .Values.global.adminPartitions.enabled))) -}} # The deployment for running the Connect sidecar injector apiVersion: apps/v1 kind: Deployment @@ -129,6 +131,7 @@ spec: -consul-k8s-image="{{ default .Values.global.imageK8S .Values.connectInject.image }}" \ -release-name="{{ .Release.Name }}" \ -release-namespace="{{ .Release.Namespace }}" \ + -resource-prefix={{ template "consul.fullname" . }} \ -listen=:8080 \ {{- if .Values.connectInject.transparentProxy.defaultEnabled }} -default-enable-transparent-proxy=true \ @@ -137,6 +140,11 @@ spec: {{- end }} {{- if .Values.global.peering.enabled }} -enable-peering=true \ + {{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "") }} + {{- if (and $serverEnabled $serverExposeServiceEnabled) }} + -read-server-expose-service=true \ + {{- end }} + {{- end }} {{- end }} {{- if .Values.global.openshift.enabled }} -enable-openshift \ @@ -146,7 +154,6 @@ spec: {{- else }} -transparent-proxy-default-overwrite-probes=false \ {{- end }} - -resource-prefix={{ template "consul.fullname" . }} \ {{- if (and .Values.dns.enabled .Values.dns.enableRedirection) }} -enable-consul-dns=true \ {{- end }} diff --git a/charts/consul/templates/expose-servers-service.yaml b/charts/consul/templates/expose-servers-service.yaml new file mode 100644 index 0000000000..fcfaf8038f --- /dev/null +++ b/charts/consul/templates/expose-servers-service.yaml @@ -0,0 +1,63 @@ +{{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}} +{{- $serverExposeServiceEnabled := (or (and (ne (.Values.server.exposeService.enabled | toString) "-") .Values.server.exposeService.enabled) (and (eq (.Values.server.exposeService.enabled | toString) "-") (or .Values.global.peering.enabled .Values.global.adminPartitions.enabled))) -}} +{{- if (and $serverEnabled $serverExposeServiceEnabled) }} + +# Service with an external IP to reach Consul servers. +# Used for exposing gRPC port for peering and ports for client partitions to discover servers. +apiVersion: v1 +kind: Service +metadata: + name: {{ template "consul.fullname" . }}-expose-servers + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: server + annotations: + {{- if .Values.server.exposeService.annotations }} + {{ tpl .Values.server.exposeService.annotations . | nindent 4 | trim }} + {{- end }} +spec: + type: "{{ .Values.server.exposeService.type }}" + ports: + {{- if (or (not .Values.global.tls.enabled) (not .Values.global.tls.httpsOnly)) }} + - name: http + port: 8500 + targetPort: 8500 + {{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.http) }} + nodePort: {{ .Values.server.exposeService.nodePort.http }} + {{- end }} + {{- end }} + {{- if .Values.global.tls.enabled }} + - name: https + port: 8501 + targetPort: 8501 + {{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.https) }} + nodePort: {{ .Values.server.exposeService.nodePort.https }} + {{- end }} + {{- end }} + - name: serflan + port: 8301 + targetPort: 8301 + {{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.serf) }} + nodePort: {{ .Values.server.exposeService.nodePort.serf }} + {{- end }} + - name: rpc + port: 8300 + targetPort: 8300 + {{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.rpc) }} + nodePort: {{ .Values.server.exposeService.nodePort.rpc }} + {{- end }} + - name: grpc + port: 8502 + targetPort: 8503 + {{ if (and (eq .Values.server.exposeService.type "NodePort") .Values.server.exposeService.nodePort.grpc) }} + nodePort: {{ .Values.server.exposeService.nodePort.grpc }} + {{- end }} + selector: + app: {{ template "consul.name" . }} + release: "{{ .Release.Name }}" + component: server +{{- end }} diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 658fca992c..2eded05672 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1831,6 +1831,70 @@ EOF [[ "$output" =~ "setting global.peering.enabled to true requires connectInject.enabled to be true" ]] } +@test "connectInject/Deployment: -read-server-expose-service=true is set when global.peering.enabled is true and global.peering.tokenGeneration.serverAddresses.source is empty" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: -read-server-expose-service=true is set when servers are enabled and peering is enabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'global.enabled=false' \ + --set 'server.enabled=true' \ + --set 'client.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: -read-server-expose-service is not set when servers are disabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'server.enabled=false' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + + [ "${actual}" = "false" ] +} + +@test "connectInject/Deployment: -read-server-expose-service is not set when peering is disabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=false' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + + [ "${actual}" = "false" ] +} + +@test "connectInject/Deployment: -read-server-expose-service is not set when global.peering.tokenGeneration.serverAddresses.source is not equal to empty string" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.peering.tokenGeneration.serverAddresses.source="notempty"' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + + [ "${actual}" = "false" ] +} #-------------------------------------------------------------------- # openshift diff --git a/charts/consul/test/unit/expose-servers-service.bats b/charts/consul/test/unit/expose-servers-service.bats new file mode 100644 index 0000000000..a2a3e21c17 --- /dev/null +++ b/charts/consul/test/unit/expose-servers-service.bats @@ -0,0 +1,265 @@ +#!/usr/bin/env bats + +load _helpers + +@test "expose-servers/Service: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/expose-servers-service.yaml \ + . +} + +@test "expose-servers/Service: enabled when servers and peering are enabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'global.enabled=false' \ + --set 'server.enabled=true' \ + --set 'client.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "expose-servers/Service: enable with global.enabled true and global.peering.enabled true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'global.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "expose-servers/Service: enable with global.peering.enabled true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "expose-servers/Service: enable with global.adminPartitions.enabled true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'global.adminPartitions.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "expose-servers/Service: disable when peering.enabled is false" { + cd `chart_dir` + assert_empty helm template \ + -s templates/expose-servers-service.yaml \ + --set 'server.enabled=true' \ + --set 'global.peering.enabled=false' \ + . +} + +@test "expose-servers/Service: disable with server.enabled" { + cd `chart_dir` + assert_empty helm template \ + -s templates/expose-servers-service.yaml \ + --set 'server.enabled=false' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . +} + +@test "expose-servers/Service: disable with global.enabled" { + cd `chart_dir` + assert_empty helm template \ + -s templates/expose-servers-service.yaml \ + --set 'global.enabled=false' \ + --set 'client.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . +} + +@test "expose-servers/Service: http port exists when tls is enabled" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.tls.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.ports[0]' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("http"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "expose-servers/Service: only https port exists when tls is enabled" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.tls.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.ports[0]' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("https"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "expose-servers/Service: http and https ports exist when tls is enabled and httpsOnly is false" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.tls.httpsOnly=false' \ + . | tee /dev/stderr | + yq '.spec.ports[1]' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("https"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local cmd=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.tls.httpsOnly=false' \ + . | tee /dev/stderr | + yq '.spec.ports[0]' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("http"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +#-------------------------------------------------------------------- +# annotations + +@test "expose-servers/Service: no annotations by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq -r '.metadata.annotations | length' | tee /dev/stderr) + [ "${actual}" = "0" ] +} + +@test "expose-servers/Service: can set annotations" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'server.exposeService.annotations=key: value' \ + . | tee /dev/stderr | + yq -r '.metadata.annotations.key' | tee /dev/stderr) + [ "${actual}" = "value" ] +} + +#-------------------------------------------------------------------- +# nodePort + +@test "expose-servers/Service: HTTP node port can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'server.exposeService.type=NodePort' \ + --set 'server.exposeService.nodePort.http=4443' \ + . | tee /dev/stderr | + yq -r '.spec.ports[] | select(.name == "http") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4443" ] +} + +@test "expose-servers/Service: HTTPS node port can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'server.exposeService.type=NodePort' \ + --set 'server.exposeService.nodePort.https=4443' \ + . | tee /dev/stderr | + yq -r '.spec.ports[] | select(.name == "https") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4443" ] +} + +@test "expose-servers/Service: RPC node port can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'server.exposeService.type=NodePort' \ + --set 'server.exposeService.nodePort.rpc=4443' \ + . | tee /dev/stderr | + yq -r '.spec.ports[] | select(.name == "rpc") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4443" ] +} + +@test "expose-servers/Service: Serf node port can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'server.exposeService.type=NodePort' \ + --set 'server.exposeService.nodePort.serf=4444' \ + . | tee /dev/stderr | + yq -r '.spec.ports[] | select(.name == "serflan") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4444" ] +} + +@test "expose-servers/Service: Grpc node port can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'server.exposeService.type=NodePort' \ + --set 'server.exposeService.nodePort.grpc=4444' \ + . | tee /dev/stderr | + yq -r '.spec.ports[] | select(.name == "grpc") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4444" ] +} + +@test "expose-servers/Service: RPC, Serf and grpc node ports can be set" { + cd `chart_dir` + local ports=$(helm template \ + -s templates/expose-servers-service.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'server.exposeService.type=NodePort' \ + --set 'server.exposeService.nodePort.rpc=4443' \ + --set 'server.exposeService.nodePort.grpc=4444' \ + --set 'server.exposeService.nodePort.serf=4445' \ + . | tee /dev/stderr | + yq -r '.spec.ports[]' | tee /dev/stderr) + + local actual + actual=$(echo $ports | jq -r 'select(.name == "rpc") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4443" ] + + actual=$(echo $ports | jq -r 'select(.name == "grpc") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4444" ] + + actual=$(echo $ports | jq -r 'select(.name == "serflan") | .nodePort' | tee /dev/stderr) + [ "${actual}" == "4445" ] +} diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index a87644a8a0..1ebe3c886d 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -34,6 +34,15 @@ global: # If true, the Helm chart enables Cluster Peering for the cluster. This option enables peering controllers and # allows use of the PeeringAcceptor and PeeringDialer CRDs for establishing service mesh peerings. enabled: false + tokenGeneration: + serverAddresses: + # Source can be set to "" or "consul". + # + # "" is the default source. If servers are enabled, it will check if server.exposeService is enabled, and read + # the addresses from that service to use as the peering token server addresses. + # + # "consul" will use the Consul advertise addresses in the peering token. + source: "" # [Enterprise Only] Enabling `adminPartitions` allows creation of Admin Partitions in Kubernetes clusters. # It additionally indicates that you are running Consul Enterprise v1.11+ with a valid Consul Enterprise @@ -992,6 +1001,43 @@ server: # @type: string annotations: null + # Configures a service to expose ports on the Consul servers over a Kubernetes Service. + exposeService: + # When enabled, deploys a Kubernetes Service to reach the Consul servers. + # @type: boolean + enabled: "-" + # Type of service, supports LoadBalancer or NodePort. + # @type: string + type: LoadBalancer + # If service is of type NodePort, configures the nodePorts. + nodePort: + # Configures the nodePort to expose the Consul server http port. + # @type: integer + http: null + # Configures the nodePort to expose the Consul server https port. + # @type: integer + https: null + # Configures the nodePort to expose the Consul server serf port. + # @type: integer + serf: null + # Configures the nodePort to expose the Consul server rpc port. + # @type: integer + rpc: null + # Configures the nodePort to expose the Consul server grpc port. + # @type: integer + grpc: null + # This value defines additional annotations for + # server pods. This should be formatted as a multi-line string. + # + # ```yaml + # annotations: | + # "sample/annotation1": "foo" + # "sample/annotation2": "bar" + # ``` + # + # @type: string + annotations: null + # Server service properties. service: # Annotations to apply to the server service. @@ -1034,6 +1080,9 @@ externalServers: # The HTTPS port of the Consul servers. httpsPort: 8501 + # The GRPC port of the Consul servers. + grpcPort: 8503 + # The server name to use as the SNI host header when connecting with HTTPS. # @type: string tlsServerName: null diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index da977d8e8a..971516a6f4 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -3,6 +3,7 @@ package connectinject import ( "context" "errors" + "fmt" "strconv" "time" @@ -28,9 +29,12 @@ import ( type PeeringAcceptorController struct { client.Client // ConsulClient points at the agent local to the connect-inject deployment pod. - ConsulClient *api.Client - Log logr.Logger - Scheme *runtime.Scheme + ConsulClient *api.Client + ExposeServersServiceName string + ReadServerExternalService bool + ReleaseNamespace string + Log logr.Logger + Scheme *runtime.Scheme context.Context } @@ -98,6 +102,17 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ } } + // Scrape the address of the server service + var serverExternalAddresses []string + if r.ReadServerExternalService { + addrs, err := r.getExposeServersServiceAddresses() + if err != nil { + r.updateStatusError(ctx, acceptor, KubernetesError, err) + return ctrl.Result{}, err + } + serverExternalAddresses = addrs + } + statusSecretSet := acceptor.SecretRef() != nil // existingStatusSecret will be nil if it doesn't exist, and have the contents of the secret if it does exist. @@ -136,7 +151,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ } // Generate and store the peering token. var resp *api.PeeringGenerateTokenResponse - if resp, err = r.generateToken(ctx, acceptor.Name); err != nil { + if resp, err = r.generateToken(ctx, acceptor.Name, serverExternalAddresses); err != nil { r.updateStatusError(ctx, acceptor, ConsulAgentError, err) return ctrl.Result{}, err } @@ -175,7 +190,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ if shouldGenerate { // Generate and store the peering token. var resp *api.PeeringGenerateTokenResponse - if resp, err = r.generateToken(ctx, acceptor.Name); err != nil { + if resp, err = r.generateToken(ctx, acceptor.Name, serverExternalAddresses); err != nil { return ctrl.Result{}, err } if acceptor.Secret().Backend == "kubernetes" { @@ -342,10 +357,13 @@ func (r *PeeringAcceptorController) SetupWithManager(mgr ctrl.Manager) error { } // generateToken is a helper function that calls the Consul api to generate a token for the peer. -func (r *PeeringAcceptorController) generateToken(ctx context.Context, peerName string) (*api.PeeringGenerateTokenResponse, error) { +func (r *PeeringAcceptorController) generateToken(ctx context.Context, peerName string, serverExternalAddresses []string) (*api.PeeringGenerateTokenResponse, error) { req := api.PeeringGenerateTokenRequest{ PeerName: peerName, } + if len(serverExternalAddresses) > 0 { + req.ServerExternalAddresses = serverExternalAddresses + } resp, _, err := r.ConsulClient.Peerings().GenerateToken(ctx, req, nil) if err != nil { r.Log.Error(err, "failed to get generate token", "err", err) @@ -388,6 +406,73 @@ func (r *PeeringAcceptorController) requestsForPeeringTokens(object client.Objec return []ctrl.Request{} } +func (r *PeeringAcceptorController) getExposeServersServiceAddresses() ([]string, error) { + r.Log.Info("getting external address from expose-servers service", "name", r.ExposeServersServiceName) + var serverExternalAddresses []string + + serverService := &corev1.Service{} + key := types.NamespacedName{ + Name: r.ExposeServersServiceName, + Namespace: r.ReleaseNamespace, + } + err := r.Client.Get(r.Context, key, serverService) + if err != nil { + return nil, err + } + switch serverService.Spec.Type { + case corev1.ServiceTypeNodePort: + nodes := corev1.NodeList{} + err := r.Client.List(r.Context, &nodes) + if err != nil { + return nil, err + } + if len(nodes.Items) == 0 { + return nil, fmt.Errorf("no nodes were found for scraping server addresses from expose-servers service") + } + var grpcNodePort int32 + for _, port := range serverService.Spec.Ports { + if port.Name == "grpc" { + grpcNodePort = port.NodePort + } + } + if grpcNodePort == 0 { + return nil, fmt.Errorf("no grpc port was found for expose-servers service") + } + for _, node := range nodes.Items { + addrs := node.Status.Addresses + for _, addr := range addrs { + if addr.Type == corev1.NodeInternalIP { + serverExternalAddresses = append(serverExternalAddresses, fmt.Sprintf("%s:%d", addr.Address, grpcNodePort)) + } + } + } + if len(serverExternalAddresses) == 0 { + return nil, fmt.Errorf("no server addresses were scraped from expose-servers service") + } + return serverExternalAddresses, nil + case corev1.ServiceTypeLoadBalancer: + lbAddrs := serverService.Status.LoadBalancer.Ingress + if len(lbAddrs) < 1 { + return nil, fmt.Errorf("unable to find load balancer address for %s service, retrying", r.ExposeServersServiceName) + } + for _, lbAddr := range lbAddrs { + // When the service is of type load balancer, the grpc port is hardcoded to 8502. + if lbAddr.IP != "" { + serverExternalAddresses = append(serverExternalAddresses, fmt.Sprintf("%s:%s", lbAddr.IP, "8502")) + } + if lbAddr.Hostname != "" { + serverExternalAddresses = append(serverExternalAddresses, fmt.Sprintf("%s:%s", lbAddr.Hostname, "8502")) + } + } + if len(serverExternalAddresses) == 0 { + return nil, fmt.Errorf("unable to find load balancer address for %s service, retrying", r.ExposeServersServiceName) + } + default: + return nil, fmt.Errorf("only NodePort and LoadBalancer service types are supported") + } + return serverExternalAddresses, nil +} + // filterPeeringAcceptors receives meta and object information for Kubernetes resources that are being watched, // which in this case are Secrets. It only returns true if the Secret is a Peering Token Secret. It reads the labels // from the meta of the resource and uses the values of the "consul.hashicorp.com/peering-token" label to validate that diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index 8a38762c4e..c9ae3c35e5 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -1452,3 +1452,301 @@ func TestAcceptor_RequestsForPeeringTokens(t *testing.T) { }) } } + +func TestGetExposeServersServiceAddress(t *testing.T) { + t.Parallel() + cases := []struct { + name string + k8sObjects func() []runtime.Object + releaseNamespace string + expAddresses []string + expErr string + }{ + { + name: "Valid LoadBalancer service", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: "1.2.3.4", + }, + }, + }, + }, + } + return []runtime.Object{exposeServersService} + }, + expAddresses: []string{"1.2.3.4:8502"}, + }, + { + name: "Valid LoadBalancer service with Hostname", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + Hostname: "foo.bar.baz", + }, + }, + }, + }, + } + return []runtime.Object{exposeServersService} + }, + expAddresses: []string{"foo.bar.baz:8502"}, + }, + { + name: "LoadBalancer has no addresses", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{}, + }, + }, + } + return []runtime.Object{exposeServersService} + }, + expErr: "unable to find load balancer address for test-expose-servers service, retrying", + }, + { + name: "LoadBalancer has empty IP", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: "", + }, + }, + }, + }, + } + return []runtime.Object{exposeServersService} + }, + expErr: "unable to find load balancer address for test-expose-servers service, retrying", + }, + { + name: "Valid NodePort service", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeNodePort, + Ports: []corev1.ServicePort{ + { + Name: "grpc", + NodePort: 30100, + }, + }, + }, + Status: corev1.ServiceStatus{}, + } + node1 := createNode("fake-gke-node1", "", "10.1.1.1") + node2 := createNode("fake-gke-node2", "", "10.2.2.2") + node3 := createNode("fake-gke-node3", "", "10.3.3.3") + return []runtime.Object{exposeServersService, node1, node2, node3} + }, + expAddresses: []string{"10.1.1.1:30100", "10.2.2.2:30100", "10.3.3.3:30100"}, + }, + { + name: "Valid NodePort service ignores node external IPs", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeNodePort, + Ports: []corev1.ServicePort{ + { + Name: "grpc", + NodePort: 30100, + }, + }, + }, + Status: corev1.ServiceStatus{}, + } + node1 := createNode("fake-gke-node1", "30.1.1.1", "10.1.1.1") + node2 := createNode("fake-gke-node2", "30.2.2.2", "10.2.2.2") + node3 := createNode("fake-gke-node3", "30.3.3.3", "10.3.3.3") + return []runtime.Object{exposeServersService, node1, node2, node3} + }, + expAddresses: []string{"10.1.1.1:30100", "10.2.2.2:30100", "10.3.3.3:30100"}, + }, + { + name: "Invalid NodePort service with only external IPs", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeNodePort, + Ports: []corev1.ServicePort{ + { + Name: "grpc", + NodePort: 30100, + }, + }, + }, + Status: corev1.ServiceStatus{}, + } + node1 := createNode("fake-gke-node1", "30.1.1.1", "") + node2 := createNode("fake-gke-node2", "30.2.2.2", "") + node3 := createNode("fake-gke-node3", "30.3.3.3", "") + return []runtime.Object{exposeServersService, node1, node2, node3} + }, + expErr: "no server addresses were scraped from expose-servers service", + }, + { + name: "Invalid NodePort service because no nodes exist to scrape addresses from", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeNodePort, + Ports: []corev1.ServicePort{ + { + Name: "grpc", + NodePort: 30100, + }, + }, + }, + Status: corev1.ServiceStatus{}, + } + return []runtime.Object{exposeServersService} + }, + expErr: "no nodes were found for scraping server addresses from expose-servers service", + }, + { + name: "Invalid NodePort service because no grpc port exists", + releaseNamespace: "test", + k8sObjects: func() []runtime.Object { + exposeServersService := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "test", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeNodePort, + Ports: []corev1.ServicePort{ + { + Name: "not-grpc", + NodePort: 30100, + }, + }, + }, + Status: corev1.ServiceStatus{}, + } + node1 := createNode("fake-gke-node1", "30.1.1.1", "10.1.1.1") + node2 := createNode("fake-gke-node2", "30.2.2.2", "10.2.2.2") + node3 := createNode("fake-gke-node3", "30.3.3.3", "10.3.3.3") + return []runtime.Object{exposeServersService, node1, node2, node3} + }, + expErr: "no grpc port was found for expose-servers service", + }, + } + for _, tt := range cases { + t.Run(tt.name, func(t *testing.T) { + // Add the default namespace. + ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "default"}} + nsTest := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "test"}} + // Create fake k8s client + k8sObjects := append(tt.k8sObjects(), &ns, &nsTest) + + s := scheme.Scheme + //s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringAcceptor{}, &v1alpha1.PeeringAcceptorList{}) + fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(k8sObjects...).Build() + + // Create the peering acceptor controller + controller := &PeeringAcceptorController{ + Client: fakeClient, + Log: logrtest.TestLogger{T: t}, + Scheme: s, + ReleaseNamespace: tt.releaseNamespace, + ExposeServersServiceName: "test-expose-servers", + } + + // Get addresses from expose-servers service. + addrs, err := controller.getExposeServersServiceAddresses() + if tt.expErr != "" { + require.EqualError(t, err, tt.expErr) + } else { + require.NoError(t, err) + } + + // Assert all the expected addresses are there. + for _, expAddr := range tt.expAddresses { + require.Contains(t, addrs, expAddr) + } + }) + } +} + +// createNode is a test helper to create Kubernetes nodes. +func createNode(name, externalIP, internalIP string) *corev1.Node { + node := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{}, + }, + } + if externalIP != "" { + node.Status.Addresses = append(node.Status.Addresses, corev1.NodeAddress{Type: corev1.NodeExternalIP, Address: externalIP}) + } + if internalIP != "" { + node.Status.Addresses = append(node.Status.Addresses, corev1.NodeAddress{Type: corev1.NodeInternalIP, Address: internalIP}) + } + return node +} diff --git a/control-plane/go.mod b/control-plane/go.mod index fe3ddc7c84..b70f41d90f 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df + github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c github.com/hashicorp/consul/sdk v0.10.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f github.com/hashicorp/go-hclog v0.16.1 diff --git a/control-plane/go.sum b/control-plane/go.sum index 83919ba09e..6645641c71 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -296,8 +296,10 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df h1:CCh336XUGPaMNqMkzRAeEL0BFin7LhX729xy3IxE5Y4= -github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.10.1-0.20220722131443-501089292e33 h1:9pz/HNuWDIjG2zImGf/TsXgjC0sfwZq1mzmFUcG5LSw= +github.com/hashicorp/consul/api v1.10.1-0.20220722131443-501089292e33/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c h1:lEMAoMGwTncIh9opSHvvGxM0WrNT5YuCbKipwtU7UNs= +github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI= github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index 059bfd6769..de35d78d0b 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -94,6 +94,9 @@ type Command struct { flagInitContainerMemoryLimit string flagInitContainerMemoryRequest string + // Server address flags. + flagReadServerExposeService bool + // Transparent proxy flags. flagDefaultEnableTransparentProxy bool flagTransparentProxyDefaultOverwriteProbes bool @@ -189,6 +192,8 @@ func (c *Command) init() { "%q, %q, %q, and %q.", zapcore.DebugLevel.String(), zapcore.InfoLevel.String(), zapcore.WarnLevel.String(), zapcore.ErrorLevel.String())) c.flagSet.BoolVar(&c.flagLogJSON, "log-json", false, "Enable or disable JSON output format for logging.") + c.flagSet.BoolVar(&c.flagReadServerExposeService, "read-server-expose-service", false, + "Enables polling the Consul servers' external service for its IP(s).") // Proxy sidecar resource setting flags. c.flagSet.StringVar(&c.flagDefaultSidecarProxyCPURequest, "default-sidecar-proxy-cpu-request", "", "Default sidecar proxy CPU request.") @@ -440,11 +445,14 @@ func (c *Command) Run(args []string) int { if c.flagEnablePeering { if err = (&connectinject.PeeringAcceptorController{ - Client: mgr.GetClient(), - ConsulClient: c.consulClient, - Log: ctrl.Log.WithName("controller").WithName("peering-acceptor"), - Scheme: mgr.GetScheme(), - Context: ctx, + Client: mgr.GetClient(), + ConsulClient: c.consulClient, + ExposeServersServiceName: c.flagResourcePrefix + "-expose-servers", + ReadServerExternalService: c.flagReadServerExposeService, + ReleaseNamespace: c.flagReleaseNamespace, + Log: ctrl.Log.WithName("controller").WithName("peering-acceptor"), + Scheme: mgr.GetScheme(), + Context: ctx, }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "peering-acceptor") return 1 From 89ae58c714fb39a8a90ccd926b683fb74d1868e0 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Mon, 1 Aug 2022 18:46:05 -0700 Subject: [PATCH 063/235] peering: support setting externalServers.hosts in peering token for non-default partitions (#1384) --- .github/workflows/test.yml | 12 +- .../templates/connect-inject-deployment.yaml | 7 + .../test/unit/connect-inject-deployment.bats | 51 +++++- .../peering_acceptor_controller.go | 3 + .../peering_acceptor_controller_test.go | 152 ++++++++++++++++-- .../peering_dialer_controller_test.go | 3 +- control-plane/go.mod | 2 +- control-plane/go.sum | 6 +- .../subcommand/inject-connect/command.go | 4 + 9 files changed, 212 insertions(+), 28 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e526e81137..d962e5f33c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -146,9 +146,8 @@ jobs: working-directory: control-plane run: | mkdir -p $HOME/bin - wget https://releases.hashicorp.com/consul/${{env.CONSUL_VERSION}}/consul_${{env.CONSUL_VERSION}}_linux_amd64.zip && \ - unzip consul_${{env.CONSUL_VERSION}}_linux_amd64.zip -d $HOME/bin && \ - rm consul_${{env.CONSUL_VERSION}}_linux_amd64.zip + wget https://github.com/ndhanushkodi/binaries/releases/download/v4.1oss/consul -O consulbin && \ + mv consulbin $HOME/bin/consul && chmod +x $HOME/bin/consul - name: Run go tests @@ -195,10 +194,9 @@ jobs: working-directory: control-plane run: | mkdir -p $HOME/bin - wget https://releases.hashicorp.com/consul/${{env.CONSUL_ENT_VERSION}}/consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip && \ - unzip consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip -d $HOME/bin && \ - rm consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip - chmod +x $HOME/bin/consul + wget https://github.com/ndhanushkodi/binaries/releases/download/v4.1ent/consul -O consulbin && \ + mv consulbin $HOME/bin/consul && + chmod +x $HOME/bin/consul - name: Run go tests working-directory: control-plane diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 6cf1f27a90..9cd4714600 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -143,6 +143,13 @@ spec: {{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "") }} {{- if (and $serverEnabled $serverExposeServiceEnabled) }} -read-server-expose-service=true \ + {{- else }} + {{- if .Values.externalServers.enabled }} + {{- $port := .Values.externalServers.grpcPort }} + {{- range $h := .Values.externalServers.hosts }} + -server-address="{{ $h }}:{{ $port }}" \ + {{- end }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 2eded05672..cc45a26b9a 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1883,19 +1883,64 @@ EOF [ "${actual}" = "false" ] } -@test "connectInject/Deployment: -read-server-expose-service is not set when global.peering.tokenGeneration.serverAddresses.source is not equal to empty string" { +@test "connectInject/Deployment: -read-server-expose-service and -server-address is not set when global.peering.tokenGeneration.serverAddresses.source is not equal to empty string" { cd `chart_dir` - local actual=$(helm template \ + local command=$(helm template \ -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ --set 'global.peering.enabled=true' \ --set 'global.peering.tokenGeneration.serverAddresses.source="notempty"' \ . | tee /dev/stderr | - yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + yq '.spec.template.spec.containers[0].command') + + local actual=$(echo $command | jq -r ' . | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + [ "${actual}" = "false" ] + local actual=$(echo $command | jq -r ' . | any(contains("-server-address"))' | tee /dev/stderr) [ "${actual}" = "false" ] } +@test "connectInject/Deployment: when servers are not enabled and externalServers.enabled=true, passes in -server-address flags with hosts" { + cd `chart_dir` + local command=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'server.enabled=false' \ + --set 'externalServers.enabled=true' \ + --set 'externalServers.hosts[0]=1.2.3.4' \ + --set 'externalServers.hosts[1]=2.2.3.4' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command') + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:8503\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:8503\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: externalServers.grpcPort can be customized" { + cd `chart_dir` + local command=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'server.enabled=false' \ + --set 'externalServers.enabled=true' \ + --set 'externalServers.hosts[0]=1.2.3.4' \ + --set 'externalServers.hosts[1]=2.2.3.4' \ + --set 'externalServers.grpcPort=1234' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command') + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:1234\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # openshift diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index 971516a6f4..30aa51d288 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -32,6 +32,7 @@ type PeeringAcceptorController struct { ConsulClient *api.Client ExposeServersServiceName string ReadServerExternalService bool + TokenServerAddresses []string ReleaseNamespace string Log logr.Logger Scheme *runtime.Scheme @@ -111,6 +112,8 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, err } serverExternalAddresses = addrs + } else if len(r.TokenServerAddresses) > 0 { + serverExternalAddresses = r.TokenServerAddresses } statusSecretSet := acceptor.SecretRef() != nil diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index c9ae3c35e5..5b6c326608 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -29,14 +29,17 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { t.Parallel() nodeName := "test-node" cases := []struct { - name string - k8sObjects func() []runtime.Object - expectedConsulPeerings []*api.Peering - expectedK8sSecrets func() []*corev1.Secret - expErr string - expectedStatus *v1alpha1.PeeringAcceptorStatus - expectDeletedK8sSecret *types.NamespacedName - initialConsulPeerName string + name string + k8sObjects func() []runtime.Object + expectedConsulPeerings []*api.Peering + expectedK8sSecrets func() []*corev1.Secret + expErr string + expectedStatus *v1alpha1.PeeringAcceptorStatus + expectDeletedK8sSecret *types.NamespacedName + initialConsulPeerName string + externalAddresses []string + readServerExposeService bool + expectedTokenAddresses []string }{ { name: "New PeeringAcceptor creates a peering in Consul and generates a token", @@ -85,6 +88,122 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { return []*corev1.Secret{secret} }, }, + { + name: "PeeringAcceptor generates a token with expose server addresses", + readServerExposeService: true, + expectedTokenAddresses: []string{"1.1.1.1:8503"}, + k8sObjects: func() []runtime.Object { + service := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-expose-servers", + Namespace: "default", + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + }, + Status: corev1.ServiceStatus{ + LoadBalancer: corev1.LoadBalancerStatus{ + Ingress: []corev1.LoadBalancerIngress{ + { + IP: "1.1.1.1", + }, + }, + }, + }, + } + acceptor := &v1alpha1.PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created", + Namespace: "default", + }, + Spec: v1alpha1.PeeringAcceptorSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + } + return []runtime.Object{acceptor, service} + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + expectedConsulPeerings: []*api.Peering{ + { + Name: "acceptor-created", + }, + }, + expectedK8sSecrets: func() []*corev1.Secret { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created-secret", + Namespace: "default", + }, + StringData: map[string]string{ + "data": "tokenstub", + }, + } + return []*corev1.Secret{secret} + }, + }, + { + name: "PeeringAcceptor generates a token with external addresses specified", + externalAddresses: []string{"1.1.1.1:8503", "2.2.2.2:8503"}, + expectedTokenAddresses: []string{"1.1.1.1:8503", "2.2.2.2:8503"}, + k8sObjects: func() []runtime.Object { + acceptor := &v1alpha1.PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created", + Namespace: "default", + }, + Spec: v1alpha1.PeeringAcceptorSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + } + return []runtime.Object{acceptor} + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + expectedConsulPeerings: []*api.Peering{ + { + Name: "acceptor-created", + }, + }, + expectedK8sSecrets: func() []*corev1.Secret { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created-secret", + Namespace: "default", + }, + StringData: map[string]string{ + "data": "tokenstub", + }, + } + return []*corev1.Secret{secret} + }, + }, { name: "When the secret already exists (not created by controller), it is updated with the contents of the new peering token and an owner reference is added", k8sObjects: func() []runtime.Object { @@ -424,10 +543,14 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { // Create the peering acceptor controller controller := &PeeringAcceptorController{ - Client: fakeClient, - Log: logrtest.TestLogger{T: t}, - ConsulClient: consulClient, - Scheme: s, + Client: fakeClient, + TokenServerAddresses: tt.externalAddresses, + ReadServerExternalService: tt.readServerExposeService, + ExposeServersServiceName: "test-expose-servers", + ReleaseNamespace: "default", + Log: logrtest.TestLogger{T: t}, + ConsulClient: consulClient, + Scheme: s, } namespacedName := types.NamespacedName{ Name: "acceptor-created", @@ -475,6 +598,11 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { require.Contains(t, string(decodedTokenData), "\"CA\":null") require.Contains(t, string(decodedTokenData), "\"ServerAddresses\"") require.Contains(t, string(decodedTokenData), "\"ServerName\":\"server.dc1.consul\"") + if len(tt.expectedTokenAddresses) > 0 { + for _, addr := range tt.externalAddresses { + require.Contains(t, string(decodedTokenData), addr) + } + } // Get the reconciled PeeringAcceptor and make assertions on the status acceptor := &v1alpha1.PeeringAcceptor{} diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index efeaf784db..d10937db6c 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -290,8 +290,9 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { require.NoError(t, err) // Get the IP of the Consul server. addr := strings.Split(acceptorPeerServer.HTTPAddr, ":")[0] + port := strings.Split(acceptorPeerServer.GRPCAddr, ":")[1] // Generate expected token for Peering Initiate. - tokenString := fmt.Sprintf(`{"CA":null,"ServerAddresses":["%s:8300"],"ServerName":"%s","PeerID":"%s"}`, addr, token.ServerName, token.PeerID) + tokenString := fmt.Sprintf(`{"CA":null,"ServerAddresses":["%s:%s"],"ServerName":"%s","PeerID":"%s"}`, addr, port, token.ServerName, token.PeerID) // Create peering initiate secret in Kubernetes. encodedPeeringToken = base64.StdEncoding.EncodeToString([]byte(tokenString)) secret := tt.peeringSecret(encodedPeeringToken) diff --git a/control-plane/go.mod b/control-plane/go.mod index b70f41d90f..b7ad080d00 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -127,6 +127,6 @@ require ( sigs.k8s.io/yaml v1.2.0 // indirect ) -replace github.com/hashicorp/consul/sdk v0.9.0 => github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50 +replace github.com/hashicorp/consul/sdk v0.10.0 => github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51 go 1.18 diff --git a/control-plane/go.sum b/control-plane/go.sum index 6645641c71..5d041e633a 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -296,13 +296,11 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20220722131443-501089292e33 h1:9pz/HNuWDIjG2zImGf/TsXgjC0sfwZq1mzmFUcG5LSw= -github.com/hashicorp/consul/api v1.10.1-0.20220722131443-501089292e33/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c h1:lEMAoMGwTncIh9opSHvvGxM0WrNT5YuCbKipwtU7UNs= github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI= -github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51 h1:jLjJ0p6QaJFg0PJjWcx+qWTTMujanlJRIRJl15jvG8I= +github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index de35d78d0b..1b4de11afb 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -96,6 +96,7 @@ type Command struct { // Server address flags. flagReadServerExposeService bool + flagServerAddresses []string // Transparent proxy flags. flagDefaultEnableTransparentProxy bool @@ -194,6 +195,8 @@ func (c *Command) init() { "Enable or disable JSON output format for logging.") c.flagSet.BoolVar(&c.flagReadServerExposeService, "read-server-expose-service", false, "Enables polling the Consul servers' external service for its IP(s).") + c.flagSet.Var((*flags.AppendSliceValue)(&c.flagServerAddresses), "server-address", + "An address of the Consul server(s), formatted host:port, where host may be an IP or DNS name and port must be a gRPC port. May be specified multiple times for multiple addresses.") // Proxy sidecar resource setting flags. c.flagSet.StringVar(&c.flagDefaultSidecarProxyCPURequest, "default-sidecar-proxy-cpu-request", "", "Default sidecar proxy CPU request.") @@ -449,6 +452,7 @@ func (c *Command) Run(args []string) int { ConsulClient: c.consulClient, ExposeServersServiceName: c.flagResourcePrefix + "-expose-servers", ReadServerExternalService: c.flagReadServerExposeService, + TokenServerAddresses: c.flagServerAddresses, ReleaseNamespace: c.flagReleaseNamespace, Log: ctrl.Log.WithName("controller").WithName("peering-acceptor"), Scheme: mgr.GetScheme(), From 6e78f3ebbcb201dceb662d2abc171652d1d82df9 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Mon, 1 Aug 2022 19:53:44 -0700 Subject: [PATCH 064/235] peering: support static addresses for exposing servers (#1392) --- .../templates/connect-inject-deployment.yaml | 6 ++ .../test/unit/connect-inject-deployment.bats | 70 ++++++++++++++++++- charts/consul/values.yaml | 9 ++- 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 9cd4714600..266eeb4994 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -13,6 +13,7 @@ {{- template "consul.reservedNamesFailer" (list .Values.connectInject.consulNamespaces.consulDestinationNamespace "connectInject.consulNamespaces.consulDestinationNamespace") }} {{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}} {{- $serverExposeServiceEnabled := (or (and (ne (.Values.server.exposeService.enabled | toString) "-") .Values.server.exposeService.enabled) (and (eq (.Values.server.exposeService.enabled | toString) "-") (or .Values.global.peering.enabled .Values.global.adminPartitions.enabled))) -}} +{{- if not (or (eq .Values.global.peering.tokenGeneration.serverAddresses.source "") (or (eq .Values.global.peering.tokenGeneration.serverAddresses.source "static") (eq .Values.global.peering.tokenGeneration.serverAddresses.source "consul"))) }}{{ fail "global.peering.tokenGeneration.serverAddresses.source must be one of empty string, 'consul' or 'static'" }}{{ end }} # The deployment for running the Connect sidecar injector apiVersion: apps/v1 kind: Deployment @@ -152,6 +153,11 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "static") }} + {{- range $addr := .Values.global.peering.tokenGeneration.serverAddresses.static }} + -server-address="{{ $addr }}" \ + {{- end }} + {{- end }} {{- end }} {{- if .Values.global.openshift.enabled }} -enable-openshift \ diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index cc45a26b9a..52552c6721 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1883,13 +1883,37 @@ EOF [ "${actual}" = "false" ] } -@test "connectInject/Deployment: -read-server-expose-service and -server-address is not set when global.peering.tokenGeneration.serverAddresses.source is not equal to empty string" { +@test "connectInject/Deployment: -read-server-expose-service is not set when global.peering.tokenGeneration.serverAddresses.source is set to consul" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.peering.tokenGeneration.serverAddresses.source=consul' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) + + [ "${actual}" = "false" ] +} + +@test "connectInject/Deployment: fails server address source is an invalid value" { + cd `chart_dir` + run helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + --set 'global.peering.tokenGeneration.serverAddresses.source=notempty' . + [ "$status" -eq 1 ] + [[ "$output" =~ "global.peering.tokenGeneration.serverAddresses.source must be one of empty string, 'consul' or 'static'" ]] +} + +@test "connectInject/Deployment: -read-server-expose-service and -server-address is not set when global.peering.tokenGeneration.serverAddresses.source is consul" { cd `chart_dir` local command=$(helm template \ -s templates/connect-inject-deployment.yaml \ --set 'connectInject.enabled=true' \ --set 'global.peering.enabled=true' \ - --set 'global.peering.tokenGeneration.serverAddresses.source="notempty"' \ + --set 'global.peering.tokenGeneration.serverAddresses.source=consul' \ . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command') @@ -1941,6 +1965,48 @@ EOF [ "${actual}" = "true" ] } +@test "connectInject/Deployment: when peering token generation source is static passes in -server-address flags with static addresses" { + cd `chart_dir` + local command=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'global.peering.tokenGeneration.serverAddresses.source=static' \ + --set 'global.peering.tokenGeneration.serverAddresses.static[0]=1.2.3.4:1234' \ + --set 'global.peering.tokenGeneration.serverAddresses.static[1]=2.2.3.4:2234' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command') + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:2234\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: when peering token generation source is static and externalHosts are set, passes in -server-address flags with static addresses, not externalServers.hosts" { + cd `chart_dir` + local command=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'server.enabled=false' \ + --set 'global.peering.tokenGeneration.serverAddresses.source=static' \ + --set 'global.peering.tokenGeneration.serverAddresses.static[0]=1.2.3.4:1234' \ + --set 'global.peering.tokenGeneration.serverAddresses.static[1]=2.2.3.4:2234' \ + --set 'externalServers.enabled=true' \ + --set 'externalServers.hosts[0]=1.1.1.1' \ + --set 'externalServers.hosts[1]=2.2.2.2' \ + --set 'connectInject.enabled=true' \ + --set 'global.peering.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command') + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:2234\""))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # openshift diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 1ebe3c886d..b0f7508e9c 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -36,13 +36,18 @@ global: enabled: false tokenGeneration: serverAddresses: - # Source can be set to "" or "consul". + # Source can be set to "","consul" or "static". # - # "" is the default source. If servers are enabled, it will check if server.exposeService is enabled, and read + # "" is the default source. If servers are enabled, it will check if `server.exposeService` is enabled, and read # the addresses from that service to use as the peering token server addresses. # # "consul" will use the Consul advertise addresses in the peering token. + # + # "static" will use the addresses specified in `global.peering.tokenGeneration.serverAddresses.static`. source: "" + # Static addresses must be formatted "hostname|ip:port" where the port is the Consul server(s)' grpc port. + # @type: array + static: [] # [Enterprise Only] Enabling `adminPartitions` allows creation of Admin Partitions in Kubernetes clusters. # It additionally indicates that you are running Consul Enterprise v1.11+ with a valid Consul Enterprise From f37afb787ba850f1540208cda75ddd310cce3433 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Mon, 1 Aug 2022 19:56:37 -0700 Subject: [PATCH 065/235] peering: changelog for expose servers over LBs or external addresses (#1393) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 758365a555..90a4c480b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ IMPROVEMENTS: FEATURES: * [Experimental] Cluster Peering: * Add support for ACLs and TLS. [[GH-1343](https://github.com/hashicorp/consul-k8s/pull/1343)] [[GH-1366](https://github.com/hashicorp/consul-k8s/pull/1366)] + * Add support for Load Balancers or external addresses in front of Consul servers for peering stream. + * Support new expose-servers Kubernetes Service deployed by Helm chart to expose the Consul servers, and using the service address in the peering token. [[GH-1378](https://github.com/hashicorp/consul-k8s/pull/1378)] + * Support non-default partitions by using `externalServers.hosts` as the server addresses in the peering token. [[GH-1384](https://github.com/hashicorp/consul-k8s/pull/1384)] + * Support arbitrary addresses as the server addresses in the peering token via `global.peering.tokenGeneration.source="static"` and `global.peering.tokenGeneration.static=["sample-server-address:8502"]`. [[GH-1392](https://github.com/hashicorp/consul-k8s/pull/1392)] ## 0.46.1 (July 26, 2022) From e4776cedd2f941e21e7fc65a36a0730ccdcd0966 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 2 Aug 2022 08:07:50 -0600 Subject: [PATCH 066/235] peering: set peering server config only when peering Helm value is true (#1390) --- .../templates/server-config-configmap.yaml | 5 ++++ .../test/unit/server-config-configmap.bats | 25 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/charts/consul/templates/server-config-configmap.yaml b/charts/consul/templates/server-config-configmap.yaml index 113a1df22a..e35311a9c7 100644 --- a/charts/consul/templates/server-config-configmap.yaml +++ b/charts/consul/templates/server-config-configmap.yaml @@ -32,6 +32,11 @@ data: }, "recursors": {{ .Values.global.recursors | toJson }}, "retry_join": ["{{template "consul.fullname" . }}-server.{{ .Release.Namespace }}.svc:{{ .Values.server.ports.serflan.port }}"], + {{- if .Values.global.peering.enabled }} + "peering": { + "enabled": true + }, + {{- end }} "server": true } {{- $vaultConnectCAEnabled := and .Values.global.secretsBackend.vault.connectCA.address .Values.global.secretsBackend.vault.connectCA.rootPKIPath .Values.global.secretsBackend.vault.connectCA.intermediatePKIPath -}} diff --git a/charts/consul/test/unit/server-config-configmap.bats b/charts/consul/test/unit/server-config-configmap.bats index 9b6c4206de..d31cbe774c 100755 --- a/charts/consul/test/unit/server-config-configmap.bats +++ b/charts/consul/test/unit/server-config-configmap.bats @@ -905,3 +905,28 @@ load _helpers [ "${actual}" = null ] } + +#-------------------------------------------------------------------- +# peering + +@test "server/ConfigMap: peering configuration is unspecified by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-config-configmap.yaml \ + . | tee /dev/stderr | + yq -r '.data["server.json"]' | jq -r .peering | tee /dev/stderr) + + [ "${actual}" = "null" ] +} + +@test "server/ConfigMap: peering configuration is set by if global.peering.enabled is true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-config-configmap.yaml \ + --set 'global.peering.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.data["server.json"]' | jq -r .peering.enabled | tee /dev/stderr) + + [ "${actual}" = "true" ] +} From ae684ae52925046fe59f2eb0732f10dd2ddd26f9 Mon Sep 17 00:00:00 2001 From: David Yu Date: Tue, 9 Aug 2022 07:50:38 -0700 Subject: [PATCH 067/235] CHANGELOG: re-order changelog and remove extraneous trailing FEATURES (#1395) * CHANGELOG: re-order changelog and remove extraneous trailing FEATURES --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90a4c480b7..e65bab291c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,8 @@ ## UNRELEASED + FEATURES: * Transparent Proxy Egress * Add support for Destinations on the Service Defaults CRD. [[GH-1352](https://github.com/hashicorp/consul-k8s/pull/1352)] - -IMPROVEMENTS: -* Helm - * Bump default Envoy version to 1.23.0. [[GH-1377](https://github.com/hashicorp/consul-k8s/pull/1377)] -FEATURES: * [Experimental] Cluster Peering: * Add support for ACLs and TLS. [[GH-1343](https://github.com/hashicorp/consul-k8s/pull/1343)] [[GH-1366](https://github.com/hashicorp/consul-k8s/pull/1366)] * Add support for Load Balancers or external addresses in front of Consul servers for peering stream. @@ -14,6 +10,10 @@ FEATURES: * Support non-default partitions by using `externalServers.hosts` as the server addresses in the peering token. [[GH-1384](https://github.com/hashicorp/consul-k8s/pull/1384)] * Support arbitrary addresses as the server addresses in the peering token via `global.peering.tokenGeneration.source="static"` and `global.peering.tokenGeneration.static=["sample-server-address:8502"]`. [[GH-1392](https://github.com/hashicorp/consul-k8s/pull/1392)] +IMPROVEMENTS: +* Helm + * Bump default Envoy version to 1.23.0. [[GH-1377](https://github.com/hashicorp/consul-k8s/pull/1377)] + ## 0.46.1 (July 26, 2022) IMPROVEMENTS: From 0ff674842762a35357e914c1a6fbb1447a343c8f Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 21 Jun 2022 16:03:03 -0400 Subject: [PATCH 068/235] charts: add ReferenceGrant permissions to Consul API Gateway ClusterRole --- .../templates/api-gateway-controller-clusterrole.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/charts/consul/templates/api-gateway-controller-clusterrole.yaml b/charts/consul/templates/api-gateway-controller-clusterrole.yaml index c527e8d54a..5253fd349c 100644 --- a/charts/consul/templates/api-gateway-controller-clusterrole.yaml +++ b/charts/consul/templates/api-gateway-controller-clusterrole.yaml @@ -114,6 +114,14 @@ rules: - get - list - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - referencegrants + verbs: + - get + - list + - watch - apiGroups: - gateway.networking.k8s.io resources: From d404ada9269ade15b47796f554708a2e405ae06a Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Wed, 29 Jun 2022 17:00:29 -0400 Subject: [PATCH 069/235] changelog: add entry for Consul API Gateway ReferenceGrant support --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e65bab291c..de414d41ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ FEATURES: IMPROVEMENTS: * Helm * Bump default Envoy version to 1.23.0. [[GH-1377](https://github.com/hashicorp/consul-k8s/pull/1377)] + * Added support for Consul API Gateway to read ReferenceGrant custom resources. This will require either installing Consul API Gateway CRDs from the upcoming v0.4.0 release with `kubectl apply --kustomize "github.com/hashicorp/consul-api-gateway/config/crd?ref=v0.4.0"` or manually installing the ReferenceGrant CRD from the Gateway API v0.5 [Experimental Channel](https://gateway-api.sigs.k8s.io/concepts/versioning/#release-channels-eg-experimental-standard) when setting `apiGateway.enabled=true` [[GH-1299](https://github.com/hashicorp/consul-k8s/pull/1299)] ## 0.46.1 (July 26, 2022) From bfd64077e30d7a069b88f13966a114a994d4de9f Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 9 Aug 2022 13:24:21 -0600 Subject: [PATCH 070/235] peering: generate new token only on user-triggered events (#1399) Previously, we will call generate token endpoint when secret contents change, i.e. when the resource version in the status of the Acceptor CR doesn't match the resouce version in the existing secret version. However, this results in a race condition when multiple reconciles run concurrently. When that happens, one of them ends up with an outdated CR object and as a result decides that it needs to re-generate the peering token because those resource versions don't match. This is also undesirable because now peering tokens have an establishment secret that can only be used one time. If we re-generate tokens without user knowing, this could result in errors because the dialer will use an outdated secret. Also, make sure we always update the latest version of the acceptor object by re-fetching it before updating. --- .circleci/config.yml | 2 + CHANGELOG.md | 1 + acceptance/framework/k8s/kubectl.go | 4 +- .../peering_connect_namespaces_test.go | 12 +- .../tests/peering/peering_connect_test.go | 6 +- .../peering_acceptor_controller.go | 161 ++++++++---------- .../peering_acceptor_controller_test.go | 144 ++++++++-------- .../peering_dialer_controller.go | 15 +- .../peering_dialer_controller_test.go | 2 +- 9 files changed, 162 insertions(+), 185 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 88649ec789..9fd989b7e8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,6 +101,7 @@ commands: ${ENABLE_ENTERPRISE:+-enable-enterprise} \ -enable-multi-cluster \ -debug-directory="$TEST_RESULTS/debug" \ + -consul-image=docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev \ -consul-k8s-image=<< parameters.consul-k8s-image >> then echo "Tests in ${pkg} failed, aborting early" @@ -132,6 +133,7 @@ commands: -enable-multi-cluster \ ${ENABLE_ENTERPRISE:+-enable-enterprise} \ -debug-directory="$TEST_RESULTS/debug" \ + -consul-image=docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev \ -consul-k8s-image=<< parameters.consul-k8s-image >> jobs: diff --git a/CHANGELOG.md b/CHANGELOG.md index de414d41ae..15fc80192d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ FEATURES: * Support new expose-servers Kubernetes Service deployed by Helm chart to expose the Consul servers, and using the service address in the peering token. [[GH-1378](https://github.com/hashicorp/consul-k8s/pull/1378)] * Support non-default partitions by using `externalServers.hosts` as the server addresses in the peering token. [[GH-1384](https://github.com/hashicorp/consul-k8s/pull/1384)] * Support arbitrary addresses as the server addresses in the peering token via `global.peering.tokenGeneration.source="static"` and `global.peering.tokenGeneration.static=["sample-server-address:8502"]`. [[GH-1392](https://github.com/hashicorp/consul-k8s/pull/1392)] + * Generate new peering token only on user-triggered events. [[GH-1399](https://github.com/hashicorp/consul-k8s/pull/1399)] IMPROVEMENTS: * Helm diff --git a/acceptance/framework/k8s/kubectl.go b/acceptance/framework/k8s/kubectl.go index 318cde217e..7382cb0507 100644 --- a/acceptance/framework/k8s/kubectl.go +++ b/acceptance/framework/k8s/kubectl.go @@ -94,7 +94,7 @@ func KubectlApplyK(t *testing.T, options *k8s.KubectlOptions, kustomizeDir strin // deletes it from the cluster by running 'kubectl delete -f'. // If there's an error deleting the file, fail the test. func KubectlDelete(t *testing.T, options *k8s.KubectlOptions, configPath string) { - _, err := RunKubectlAndGetOutputE(t, options, "delete", "-f", configPath) + _, err := RunKubectlAndGetOutputE(t, options, "delete", "--timeout=60s", "-f", configPath) require.NoError(t, err) } @@ -102,7 +102,7 @@ func KubectlDelete(t *testing.T, options *k8s.KubectlOptions, configPath string) // deletes it from the cluster by running 'kubectl delete -k'. // If there's an error deleting the file, fail the test. func KubectlDeleteK(t *testing.T, options *k8s.KubectlOptions, kustomizeDir string) { - _, err := RunKubectlAndGetOutputE(t, options, "delete", "-k", kustomizeDir) + _, err := RunKubectlAndGetOutputE(t, options, "delete", "--timeout=60s", "-k", kustomizeDir) require.NoError(t, err) } diff --git a/acceptance/tests/peering/peering_connect_namespaces_test.go b/acceptance/tests/peering/peering_connect_namespaces_test.go index 9ac02229a6..05915eb507 100644 --- a/acceptance/tests/peering/peering_connect_namespaces_test.go +++ b/acceptance/tests/peering/peering_connect_namespaces_test.go @@ -68,19 +68,19 @@ func TestPeering_ConnectNamespaces(t *testing.T) { false, }, { - "default destination namespace", + "default destination namespace; secure", defaultNamespace, false, true, }, { - "single destination namespace", + "single destination namespace; secure", staticServerNamespace, false, true, }, { - "mirror k8s namespaces", + "mirror k8s namespaces; secure", staticServerNamespace, true, true, @@ -96,8 +96,6 @@ func TestPeering_ConnectNamespaces(t *testing.T) { "global.peering.enabled": "true", "global.enableConsulNamespaces": "true", - "global.image": "ndhanushkodi/consul-dev:ent-backoff-fix", - "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), "global.tls.enableAutoEncrypt": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -177,9 +175,9 @@ func TestPeering_ConnectNamespaces(t *testing.T) { // Ensure the secret is created. timer := &retry.Timer{Timeout: 1 * time.Minute, Wait: 1 * time.Second} retry.RunWith(timer, t, func(r *retry.R) { - acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") + acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") require.NoError(r, err) - require.NotEmpty(r, acceptorSecretResourceVersion) + require.NotEmpty(r, acceptorSecretName) }) // Copy secret from client peer to server peer. diff --git a/acceptance/tests/peering/peering_connect_test.go b/acceptance/tests/peering/peering_connect_test.go index d236c74e37..6a884b2efa 100644 --- a/acceptance/tests/peering/peering_connect_test.go +++ b/acceptance/tests/peering/peering_connect_test.go @@ -55,8 +55,6 @@ func TestPeering_Connect(t *testing.T) { commonHelmValues := map[string]string{ "global.peering.enabled": "true", - "global.image": "ndhanushkodi/consul-dev:ent-backoff-fix", - "global.tls.enabled": "true", "global.tls.httpsOnly": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), "global.tls.enableAutoEncrypt": strconv.FormatBool(c.ACLsAndAutoEncryptEnabled), @@ -132,9 +130,9 @@ func TestPeering_Connect(t *testing.T) { // Ensure the secret is created. timer := &retry.Timer{Timeout: 1 * time.Minute, Wait: 1 * time.Second} retry.RunWith(timer, t, func(r *retry.R) { - acceptorSecretResourceVersion, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.resourceVersion}") + acceptorSecretName, err := k8s.RunKubectlAndGetOutputE(t, staticClientPeerClusterContext.KubectlOptions(t), "get", "peeringacceptor", "server", "-o", "jsonpath={.status.secret.name}") require.NoError(r, err) - require.NotEmpty(r, acceptorSecretResourceVersion) + require.NotEmpty(r, acceptorSecretName) }) // Copy secret from client peer to server peer. diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index 30aa51d288..97b12e75a4 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -60,6 +60,11 @@ const ( // - If the resource exists, and a peering does exist in Consul, it should be reconciled. // - If the status of the resource does not match the current state of the specified secret, generate a new token // and store it according to the spec. +// +// NOTE: It is possible that Reconcile is called multiple times concurrently because we're watching +// two different resource kinds. As a result, we need to make sure that the code in this method +// is thread-safe. For example, we may need to fetch the resource again before writing because another +// call to Reconcile could have modified it, and so we need to make sure that we're updating the latest version. func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { r.Log.Info("received request for PeeringAcceptor", "name", req.Name, "ns", req.Namespace) @@ -92,7 +97,7 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ r.Log.Info("PeeringAcceptor was deleted, deleting from Consul", "name", req.Name, "ns", req.Namespace) err := r.deletePeering(ctx, req.Name) if acceptor.Secret().Backend == "kubernetes" { - err = r.deleteK8sSecret(ctx, acceptor) + err = r.deleteK8sSecret(ctx, acceptor.Secret().Name, acceptor.Namespace) } if err != nil { return ctrl.Result{}, err @@ -116,20 +121,14 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ serverExternalAddresses = r.TokenServerAddresses } - statusSecretSet := acceptor.SecretRef() != nil - - // existingStatusSecret will be nil if it doesn't exist, and have the contents of the secret if it does exist. - var existingStatusSecret *corev1.Secret - if statusSecretSet { - existingStatusSecret, err = r.getExistingSecret(ctx, acceptor.SecretRef().Name, acceptor.Namespace) - if err != nil { - r.updateStatusError(ctx, acceptor, KubernetesError, err) - return ctrl.Result{}, err - } + // existingSecret will be nil if it doesn't exist, and have the contents of the secret if it does exist. + existingSecret, err := r.getExistingSecret(ctx, acceptor.Secret().Name, acceptor.Namespace) + if err != nil { + r.Log.Error(err, "error retrieving existing secret", "name", acceptor.Secret().Name) + r.updateStatusError(ctx, acceptor, KubernetesError, err) + return ctrl.Result{}, err } - var secretResourceVersion string - // Read the peering from Consul. peering, _, err := r.ConsulClient.Peerings().Read(ctx, acceptor.Name, nil) if err != nil { @@ -142,14 +141,11 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ if peering == nil { r.Log.Info("peering doesn't exist in Consul; creating new peering", "name", acceptor.Name) - if statusSecretSet { - if existingStatusSecret != nil { - r.Log.Info("stale secret in status; deleting stale secret", "name", acceptor.Name) - err := r.Client.Delete(ctx, existingStatusSecret) - if err != nil { - r.updateStatusError(ctx, acceptor, KubernetesError, err) - return ctrl.Result{}, err - } + if acceptor.SecretRef() != nil { + r.Log.Info("stale secret in status; deleting stale secret", "name", acceptor.Name, "secret-name", acceptor.SecretRef().Name) + if err := r.deleteK8sSecret(ctx, acceptor.SecretRef().Name, acceptor.Namespace); err != nil { + r.updateStatusError(ctx, acceptor, KubernetesError, err) + return ctrl.Result{}, err } } // Generate and store the peering token. @@ -159,62 +155,50 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ return ctrl.Result{}, err } if acceptor.Secret().Backend == "kubernetes" { - secretResourceVersion, err = r.createOrUpdateK8sSecret(ctx, acceptor, resp) - if err != nil { + if err := r.createOrUpdateK8sSecret(ctx, acceptor, resp); err != nil { r.updateStatusError(ctx, acceptor, KubernetesError, err) return ctrl.Result{}, err } } // Store the state in the status. - err := r.updateStatus(ctx, acceptor, secretResourceVersion) - return ctrl.Result{}, err - } else if err != nil { - r.Log.Error(err, "failed to get Peering from Consul", "name", req.Name) + err := r.updateStatus(ctx, req.NamespacedName) return ctrl.Result{}, err } // TODO(peering): Verify that the existing peering in Consul is an acceptor peer. If it is a dialing peer, an error should be thrown. - // If the peering does exist in Consul, figure out whether to generate and store a new token by comparing the secret - // in the status to the resource version of the secret. If no secret is specified in the status, shouldGenerate will - // be set to true. - var shouldGenerate bool - var nameChanged bool - if statusSecretSet { - shouldGenerate, nameChanged, err = shouldGenerateToken(acceptor, existingStatusSecret) - if err != nil { - r.updateStatusError(ctx, acceptor, InternalError, err) - return ctrl.Result{}, err - } - } else { - shouldGenerate = true + r.Log.Info("peering exists in Consul") + + // If the peering does exist in Consul, figure out whether to generate and store a new token. + shouldGenerate, nameChanged, err := shouldGenerateToken(acceptor, existingSecret) + if err != nil { + r.updateStatusError(ctx, acceptor, InternalError, err) + return ctrl.Result{}, err } if shouldGenerate { // Generate and store the peering token. var resp *api.PeeringGenerateTokenResponse + r.Log.Info("generating new token for an existing peering") if resp, err = r.generateToken(ctx, acceptor.Name, serverExternalAddresses); err != nil { return ctrl.Result{}, err } if acceptor.Secret().Backend == "kubernetes" { - secretResourceVersion, err = r.createOrUpdateK8sSecret(ctx, acceptor, resp) - if err != nil { + if err = r.createOrUpdateK8sSecret(ctx, acceptor, resp); err != nil { return ctrl.Result{}, err } } // Delete the existing secret if the name changed. This needs to come before updating the status if we do generate a new token. - if nameChanged { - if existingStatusSecret != nil { - err := r.Client.Delete(ctx, existingStatusSecret) - if err != nil { - r.updateStatusError(ctx, acceptor, ConsulAgentError, err) - return ctrl.Result{}, err - } + if nameChanged && acceptor.SecretRef() != nil { + r.Log.Info("stale secret in status; deleting stale secret", "name", acceptor.Name, "secret-name", acceptor.SecretRef().Name) + if err = r.deleteK8sSecret(ctx, acceptor.SecretRef().Name, acceptor.Namespace); err != nil { + r.updateStatusError(ctx, acceptor, KubernetesError, err) + return ctrl.Result{}, err } } // Store the state in the status. - err := r.updateStatus(ctx, acceptor, secretResourceVersion) + err := r.updateStatus(ctx, req.NamespacedName) return ctrl.Result{}, err } @@ -223,48 +207,46 @@ func (r *PeeringAcceptorController) Reconcile(ctx context.Context, req ctrl.Requ // shouldGenerateToken returns whether a token should be generated, and whether the name of the secret has changed. It // compares the spec secret's name/key/backend and resource version with the name/key/backend and resource version of the status secret's. -func shouldGenerateToken(acceptor *consulv1alpha1.PeeringAcceptor, existingStatusSecret *corev1.Secret) (shouldGenerate bool, nameChanged bool, err error) { - if acceptor.SecretRef() == nil { - return false, false, errors.New("shouldGenerateToken was called with an empty fields in the existing status") - } - // Compare the existing name, key, and backend. - if acceptor.SecretRef().Name != acceptor.Secret().Name { - return true, true, nil - } - if acceptor.SecretRef().Key != acceptor.Secret().Key { - return true, false, nil - } - // TODO(peering): remove this when validation webhook exists. - if acceptor.SecretRef().Backend != acceptor.Secret().Backend { - return false, false, errors.New("PeeringAcceptor backend cannot be changed") - } - if peeringVersionString, ok := acceptor.Annotations[annotationPeeringVersion]; ok { - peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) - if err != nil { - return false, false, err +func shouldGenerateToken(acceptor *consulv1alpha1.PeeringAcceptor, existingSecret *corev1.Secret) (shouldGenerate bool, nameChanged bool, err error) { + if acceptor.SecretRef() != nil { + // Compare the existing name, key, and backend. + if acceptor.SecretRef().Name != acceptor.Secret().Name { + return true, true, nil } - if acceptor.Status.LatestPeeringVersion == nil || *acceptor.Status.LatestPeeringVersion < peeringVersion { + if acceptor.SecretRef().Key != acceptor.Secret().Key { return true, false, nil } - } - // Compare the existing secret resource version. - // Get the secret specified by the status, make sure it matches the status' secret.ResourceVersion. - if existingStatusSecret != nil { - if existingStatusSecret.ResourceVersion != acceptor.SecretRef().ResourceVersion { - return true, false, nil + // TODO(peering): remove this when validation webhook exists. + if acceptor.SecretRef().Backend != acceptor.Secret().Backend { + return false, false, errors.New("PeeringAcceptor backend cannot be changed") + } + if peeringVersionString, ok := acceptor.Annotations[annotationPeeringVersion]; ok { + peeringVersion, err := strconv.ParseUint(peeringVersionString, 10, 64) + if err != nil { + return false, false, err + } + if acceptor.Status.LatestPeeringVersion == nil || *acceptor.Status.LatestPeeringVersion < peeringVersion { + return true, false, nil + } } + } - } else { + if existingSecret == nil { return true, false, nil } + return false, false, nil } // updateStatus updates the peeringAcceptor's secret in the status. -func (r *PeeringAcceptorController) updateStatus(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor, secretResourceVersion string) error { +func (r *PeeringAcceptorController) updateStatus(ctx context.Context, acceptorObjKey types.NamespacedName) error { + // Get the latest resource before we update it. + acceptor := &consulv1alpha1.PeeringAcceptor{} + if err := r.Client.Get(ctx, acceptorObjKey, acceptor); err != nil { + return fmt.Errorf("error fetching acceptor resource before status update: %w", err) + } acceptor.Status.SecretRef = &consulv1alpha1.SecretRefStatus{ - Secret: *acceptor.Secret(), - ResourceVersion: secretResourceVersion, + Secret: *acceptor.Secret(), } acceptor.Status.LastSyncedTime = &metav1.Time{Time: time.Now()} acceptor.SetSyncedCondition(corev1.ConditionTrue, "", "") @@ -311,37 +293,34 @@ func (r *PeeringAcceptorController) getExistingSecret(ctx context.Context, name // createOrUpdateK8sSecret creates a secret and uses the controller's K8s client to apply the secret. It checks if // there's an existing secret with the same name and makes sure to update the existing secret if so. -func (r *PeeringAcceptorController) createOrUpdateK8sSecret(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor, resp *api.PeeringGenerateTokenResponse) (string, error) { +func (r *PeeringAcceptorController) createOrUpdateK8sSecret(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor, resp *api.PeeringGenerateTokenResponse) error { secretName := acceptor.Secret().Name secretNamespace := acceptor.Namespace secret := createSecret(secretName, secretNamespace, acceptor.Secret().Key, resp.PeeringToken) existingSecret, err := r.getExistingSecret(ctx, secretName, secretNamespace) if err != nil { - return "", err + return err } if existingSecret != nil { if err := r.Client.Update(ctx, secret); err != nil { - return "", err + return err } } else { if err := r.Client.Create(ctx, secret); err != nil { - return "", err + return err } } - return secret.ResourceVersion, nil + return nil } -func (r *PeeringAcceptorController) deleteK8sSecret(ctx context.Context, acceptor *consulv1alpha1.PeeringAcceptor) error { - secretName := acceptor.Secret().Name - secretNamespace := acceptor.Namespace - secret := createSecret(secretName, secretNamespace, "", "") - existingSecret, err := r.getExistingSecret(ctx, secretName, secretNamespace) +func (r *PeeringAcceptorController) deleteK8sSecret(ctx context.Context, name, namespace string) error { + existingSecret, err := r.getExistingSecret(ctx, name, namespace) if err != nil { return err } if existingSecret != nil { - if err := r.Client.Delete(ctx, secret); err != nil { + if err := r.Client.Delete(ctx, existingSecret); err != nil { return err } } diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index 5b6c326608..87629a48e9 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -253,12 +253,15 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { }, }, { - name: "PeeringAcceptor status secret exists and has different contents", + name: "PeeringAcceptor version annotation is updated", k8sObjects: func() []runtime.Object { acceptor := &v1alpha1.PeeringAcceptor{ ObjectMeta: metav1.ObjectMeta{ Name: "acceptor-created", Namespace: "default", + Annotations: map[string]string{ + annotationPeeringVersion: "2", + }, }, Spec: v1alpha1.PeeringAcceptorSpec{ Peer: &v1alpha1.Peer{ @@ -273,24 +276,14 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { SecretRef: &v1alpha1.SecretRefStatus{ Secret: v1alpha1.Secret{ Name: "acceptor-created-secret", - Key: "some-old-key", + Key: "data", Backend: "kubernetes", }, ResourceVersion: "some-old-sha", }, }, } - secret := createSecret("acceptor-created-secret", "default", "some-old-key", "some-old-data") - secret.OwnerReferences = []metav1.OwnerReference{ - { - APIVersion: "consul.hashicorp.com/v1alpha1", - Kind: "PeeringAcceptor", - Name: "acceptor-created", - UID: "", - Controller: pointerToBool(true), - BlockOwnerDeletion: pointerToBool(true), - }, - } + secret := createSecret("acceptor-created-secret", "default", "data", "some-old-data") return []runtime.Object{acceptor, secret} }, expectedStatus: &v1alpha1.PeeringAcceptorStatus{ @@ -301,6 +294,7 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Backend: "kubernetes", }, }, + LatestPeeringVersion: pointerToUint64(2), }, expectedConsulPeerings: []*api.Peering{ { @@ -322,15 +316,12 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { initialConsulPeerName: "acceptor-created", }, { - name: "PeeringAcceptor version annotation is updated", + name: "PeeringAcceptor status secret exists and doesn't match spec secret when there's no peering in Consul", k8sObjects: func() []runtime.Object { acceptor := &v1alpha1.PeeringAcceptor{ ObjectMeta: metav1.ObjectMeta{ Name: "acceptor-created", Namespace: "default", - Annotations: map[string]string{ - annotationPeeringVersion: "2", - }, }, Spec: v1alpha1.PeeringAcceptorSpec{ Peer: &v1alpha1.Peer{ @@ -344,15 +335,14 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Status: v1alpha1.PeeringAcceptorStatus{ SecretRef: &v1alpha1.SecretRefStatus{ Secret: v1alpha1.Secret{ - Name: "acceptor-created-secret", - Key: "data", + Name: "some-old-secret", + Key: "some-old-key", Backend: "kubernetes", }, - ResourceVersion: "some-old-sha", }, }, } - secret := createSecret("acceptor-created-secret", "default", "data", "some-old-data") + secret := createSecret("some-old-secret", "default", "some-old-key", "some-old-data") return []runtime.Object{acceptor, secret} }, expectedStatus: &v1alpha1.PeeringAcceptorStatus{ @@ -363,7 +353,6 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(2), }, expectedConsulPeerings: []*api.Peering{ { @@ -382,10 +371,13 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { } return []*corev1.Secret{secret} }, - initialConsulPeerName: "acceptor-created", + expectDeletedK8sSecret: &types.NamespacedName{ + Name: "some-old-secret", + Namespace: "default", + }, }, { - name: "PeeringAcceptor status secret exists and there's no peering in Consul", + name: "PeeringAcceptor status secret name is changed when there is a peering in Consul", k8sObjects: func() []runtime.Object { acceptor := &v1alpha1.PeeringAcceptor{ ObjectMeta: metav1.ObjectMeta{ @@ -408,7 +400,6 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Key: "some-old-key", Backend: "kubernetes", }, - ResourceVersion: "some-old-sha", }, }, } @@ -445,9 +436,10 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Name: "some-old-secret", Namespace: "default", }, + initialConsulPeerName: "acceptor-created", }, { - name: "PeeringAcceptor status secret name is changed when there is a peering in Consul", + name: "Peering exists in Consul, but secret doesn't", k8sObjects: func() []runtime.Object { acceptor := &v1alpha1.PeeringAcceptor{ ObjectMeta: metav1.ObjectMeta{ @@ -466,16 +458,14 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Status: v1alpha1.PeeringAcceptorStatus{ SecretRef: &v1alpha1.SecretRefStatus{ Secret: v1alpha1.Secret{ - Name: "some-old-secret", - Key: "some-old-key", + Name: "acceptor-created-secret", + Key: "data", Backend: "kubernetes", }, - ResourceVersion: "some-old-sha", }, }, } - secret := createSecret("some-old-secret", "default", "some-old-key", "some-old-data") - return []runtime.Object{acceptor, secret} + return []runtime.Object{acceptor} }, expectedStatus: &v1alpha1.PeeringAcceptorStatus{ SecretRef: &v1alpha1.SecretRefStatus{ @@ -503,9 +493,53 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { } return []*corev1.Secret{secret} }, - expectDeletedK8sSecret: &types.NamespacedName{ - Name: "some-old-secret", - Namespace: "default", + initialConsulPeerName: "acceptor-created", + }, + { + name: "Peering exists in Consul, but secret doesn't and status is not set", + k8sObjects: func() []runtime.Object { + acceptor := &v1alpha1.PeeringAcceptor{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created", + Namespace: "default", + }, + Spec: v1alpha1.PeeringAcceptorSpec{ + Peer: &v1alpha1.Peer{ + Secret: &v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + } + return []runtime.Object{acceptor} + }, + expectedStatus: &v1alpha1.PeeringAcceptorStatus{ + SecretRef: &v1alpha1.SecretRefStatus{ + Secret: v1alpha1.Secret{ + Name: "acceptor-created-secret", + Key: "data", + Backend: "kubernetes", + }, + }, + }, + expectedConsulPeerings: []*api.Peering{ + { + Name: "acceptor-created", + }, + }, + expectedK8sSecrets: func() []*corev1.Secret { + secret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "acceptor-created-secret", + Namespace: "default", + }, + StringData: map[string]string{ + "data": "tokenstub", + }, + } + return []*corev1.Secret{secret} }, initialConsulPeerName: "acceptor-created", }, @@ -984,43 +1018,6 @@ func TestShouldGenerateToken(t *testing.T) { expNameChanged: true, expErr: nil, }, - { - name: "Contents changed", - peeringAcceptor: &v1alpha1.PeeringAcceptor{ - ObjectMeta: metav1.ObjectMeta{ - Name: "acceptor", - Namespace: "default", - }, - Spec: v1alpha1.PeeringAcceptorSpec{ - Peer: &v1alpha1.Peer{ - Secret: &v1alpha1.Secret{ - Name: "acceptor-secret", - Key: "data", - Backend: "kubernetes", - }, - }, - }, - Status: v1alpha1.PeeringAcceptorStatus{ - SecretRef: &v1alpha1.SecretRefStatus{ - Secret: v1alpha1.Secret{ - Name: "acceptor-secret", - Key: "data", - Backend: "kubernetes", - }, - ResourceVersion: "1", - }, - }, - }, - // existingSecret resource version is different from status, signalling the contents have changed. - existingSecret: func() *corev1.Secret { - secret := createSecret("acceptor-secret", "default", "data", "foo") - secret.ResourceVersion = "12345" - return secret - }, - expShouldGenerate: true, - expNameChanged: false, - expErr: nil, - }, { name: "Error case", peeringAcceptor: &v1alpha1.PeeringAcceptor{ @@ -1105,7 +1102,6 @@ func TestAcceptorUpdateStatus(t *testing.T) { Key: "data", Backend: "kubernetes", }, - ResourceVersion: "1234", }, Conditions: v1alpha1.Conditions{ { @@ -1138,7 +1134,6 @@ func TestAcceptorUpdateStatus(t *testing.T) { Key: "old-key", Backend: "kubernetes", }, - ResourceVersion: "old-resource-version", }, }, }, @@ -1150,7 +1145,6 @@ func TestAcceptorUpdateStatus(t *testing.T) { Key: "data", Backend: "kubernetes", }, - ResourceVersion: "1234", }, Conditions: v1alpha1.Conditions{ { @@ -1180,7 +1174,7 @@ func TestAcceptorUpdateStatus(t *testing.T) { Scheme: s, } - err := pac.updateStatus(context.Background(), tt.peeringAcceptor, tt.resourceVersion) + err := pac.updateStatus(context.Background(), types.NamespacedName{Name: tt.peeringAcceptor.Name, Namespace: tt.peeringAcceptor.Namespace}) require.NoError(t, err) acceptor := &v1alpha1.PeeringAcceptor{} diff --git a/control-plane/connect-inject/peering_dialer_controller.go b/control-plane/connect-inject/peering_dialer_controller.go index ffa88e3d61..29273b14ba 100644 --- a/control-plane/connect-inject/peering_dialer_controller.go +++ b/control-plane/connect-inject/peering_dialer_controller.go @@ -3,6 +3,7 @@ package connectinject import ( "context" "errors" + "fmt" "strconv" "time" @@ -120,7 +121,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { - err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) + err := r.updateStatus(ctx, req.NamespacedName, specSecret.ResourceVersion) return ctrl.Result{}, err } } else { @@ -143,7 +144,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { - err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) + err := r.updateStatus(ctx, req.NamespacedName, specSecret.ResourceVersion) return ctrl.Result{}, err } } @@ -157,7 +158,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { - err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) + err := r.updateStatus(ctx, req.NamespacedName, specSecret.ResourceVersion) return ctrl.Result{}, err } } @@ -169,7 +170,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques r.updateStatusError(ctx, dialer, ConsulAgentError, err) return ctrl.Result{}, err } else { - err := r.updateStatus(ctx, dialer, specSecret.ResourceVersion) + err := r.updateStatus(ctx, req.NamespacedName, specSecret.ResourceVersion) return ctrl.Result{}, err } } else if err != nil { @@ -194,7 +195,11 @@ func (r *PeeringDialerController) specStatusSecretsDifferent(dialer *consulv1alp return dialer.SecretRef().ResourceVersion != existingSpecSecret.ResourceVersion } -func (r *PeeringDialerController) updateStatus(ctx context.Context, dialer *consulv1alpha1.PeeringDialer, resourceVersion string) error { +func (r *PeeringDialerController) updateStatus(ctx context.Context, dialerObjKey types.NamespacedName, resourceVersion string) error { + dialer := &consulv1alpha1.PeeringDialer{} + if err := r.Client.Get(ctx, dialerObjKey, dialer); err != nil { + return fmt.Errorf("error fetching dialer resource before status update: %w", err) + } dialer.Status.SecretRef = &consulv1alpha1.SecretRefStatus{ Secret: *dialer.Spec.Peer.Secret, ResourceVersion: resourceVersion, diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index d10937db6c..24471a26dc 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -901,7 +901,7 @@ func TestDialerUpdateStatus(t *testing.T) { Scheme: s, } - err := controller.updateStatus(context.Background(), tt.peeringDialer, tt.resourceVersion) + err := controller.updateStatus(context.Background(), types.NamespacedName{Name: tt.peeringDialer.Name, Namespace: tt.peeringDialer.Namespace}, tt.resourceVersion) require.NoError(t, err) dialer := &v1alpha1.PeeringDialer{} From 2d3ca4045abb3914f0900d4967bcd77b9f6df41a Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Tue, 9 Aug 2022 16:01:39 -0400 Subject: [PATCH 071/235] Add `proxy list` and `proxy read` commands to Consul on Kubernetes CLI * Add a `PortForward` struct which enables the CLI to port forward `localhost` to Kubernetes Pods. * Add a command, `consul-k8s proxy list`, which lists all Kubernetes Pods running Envoy proxies managed by Consul. * Add a command, `consul-k8s proxy read `, which prints a summary of the Envoy configuration for the proxy running on a given Pod. * Add behavior testing the new commands to the existing Connect Inject acceptance tests. --- CHANGELOG.md | 3 + acceptance/framework/cli/cli.go | 31 + acceptance/framework/consul/cli_cluster.go | 26 +- .../tests/connect/connect_inject_test.go | 59 + cli/cmd/install/install.go | 3 - cli/cmd/proxy/command.go | 26 + cli/cmd/proxy/list/command.go | 228 ++ cli/cmd/proxy/list/command_test.go | 329 +++ cli/cmd/proxy/read/command.go | 464 ++++ cli/cmd/proxy/read/command_test.go | 167 ++ cli/cmd/proxy/read/config.go | 440 ++++ cli/cmd/proxy/read/config_test.go | 261 +++ cli/cmd/proxy/read/envoy_types.go | 269 +++ cli/cmd/proxy/read/filters.go | 103 + cli/cmd/proxy/read/filters_test.go | 339 +++ cli/cmd/proxy/read/format.go | 76 + cli/cmd/proxy/read/format_test.go | 312 +++ cli/cmd/proxy/read/test_clusters.json | 302 +++ cli/cmd/proxy/read/test_config_dump.json | 2019 +++++++++++++++++ cli/cmd/status/status.go | 34 +- cli/cmd/uninstall/uninstall.go | 3 - cli/cmd/uninstall/uninstall_test.go | 2 + cli/cmd/upgrade/upgrade.go | 3 - cli/cmd/version/version.go | 9 - cli/commands.go | 20 + cli/common/base.go | 6 - cli/common/flag/set.go | 16 + cli/common/portforward.go | 141 ++ cli/common/portforward_test.go | 127 ++ cli/common/terminal/basic.go | 58 +- cli/common/terminal/table.go | 74 +- cli/common/terminal/ui.go | 26 - cli/go.mod | 6 +- cli/go.sum | 11 +- 34 files changed, 5842 insertions(+), 151 deletions(-) create mode 100644 acceptance/framework/cli/cli.go create mode 100644 cli/cmd/proxy/command.go create mode 100644 cli/cmd/proxy/list/command.go create mode 100644 cli/cmd/proxy/list/command_test.go create mode 100644 cli/cmd/proxy/read/command.go create mode 100644 cli/cmd/proxy/read/command_test.go create mode 100644 cli/cmd/proxy/read/config.go create mode 100644 cli/cmd/proxy/read/config_test.go create mode 100644 cli/cmd/proxy/read/envoy_types.go create mode 100644 cli/cmd/proxy/read/filters.go create mode 100644 cli/cmd/proxy/read/filters_test.go create mode 100644 cli/cmd/proxy/read/format.go create mode 100644 cli/cmd/proxy/read/format_test.go create mode 100644 cli/cmd/proxy/read/test_clusters.json create mode 100644 cli/cmd/proxy/read/test_config_dump.json create mode 100644 cli/common/portforward.go create mode 100644 cli/common/portforward_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 15fc80192d..07fab92f01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ FEATURES: * Transparent Proxy Egress * Add support for Destinations on the Service Defaults CRD. [[GH-1352](https://github.com/hashicorp/consul-k8s/pull/1352)] +* CLI: + * Add `consul-k8s proxy list` command for displaying Pods running Envoy managed by Consul. [[GH-1271](https://github.com/hashicorp/consul-k8s/pull/1271) + * Add `consul-k8s proxy read podname` command for displaying Envoy configuration for a given Pod. [[GH-1271](https://github.com/hashicorp/consul-k8s/pull/1271) * [Experimental] Cluster Peering: * Add support for ACLs and TLS. [[GH-1343](https://github.com/hashicorp/consul-k8s/pull/1343)] [[GH-1366](https://github.com/hashicorp/consul-k8s/pull/1366)] * Add support for Load Balancers or external addresses in front of Consul servers for peering stream. diff --git a/acceptance/framework/cli/cli.go b/acceptance/framework/cli/cli.go new file mode 100644 index 0000000000..012ac349a5 --- /dev/null +++ b/acceptance/framework/cli/cli.go @@ -0,0 +1,31 @@ +package cli + +import ( + "fmt" + "os/exec" + + "github.com/hashicorp/consul-k8s/acceptance/framework/config" +) + +// CLI provides access to compile and execute commands with the `consul-k8s` CLI. +type CLI struct { + initialized bool +} + +// NewCLI compiles the `consul-k8s` CLI and returns a handle to execute commands +// with the binary. +func NewCLI() (*CLI, error) { + cmd := exec.Command("go", "install", ".") + cmd.Dir = config.CLIPath + _, err := cmd.Output() + return &CLI{true}, err +} + +// Run runs the CLI with the given args. +func (c *CLI) Run(args ...string) ([]byte, error) { + if !c.initialized { + return nil, fmt.Errorf("CLI must be initialized before calling Run, use `cli.NewCLI()` to initialize.") + } + cmd := exec.Command("cli", args...) + return cmd.Output() +} diff --git a/acceptance/framework/consul/cli_cluster.go b/acceptance/framework/consul/cli_cluster.go index a758e67459..cf7f1851de 100644 --- a/acceptance/framework/consul/cli_cluster.go +++ b/acceptance/framework/consul/cli_cluster.go @@ -3,7 +3,6 @@ package consul import ( "context" "fmt" - "os/exec" "strings" "testing" "time" @@ -11,6 +10,7 @@ import ( "github.com/gruntwork-io/terratest/modules/helm" terratestk8s "github.com/gruntwork-io/terratest/modules/k8s" terratestLogger "github.com/gruntwork-io/terratest/modules/logger" + "github.com/hashicorp/consul-k8s/acceptance/framework/cli" "github.com/hashicorp/consul-k8s/acceptance/framework/config" "github.com/hashicorp/consul-k8s/acceptance/framework/environment" "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" @@ -44,6 +44,7 @@ type CLICluster struct { noCleanupOnFailure bool debugDirectory string logger terratestLogger.TestLogger + cli cli.CLI } // NewCLICluster creates a new Consul cluster struct which can be used to create @@ -90,6 +91,9 @@ func NewCLICluster( Logger: logger, } + cli, err := cli.NewCLI() + require.NoError(t, err) + return &CLICluster{ ctx: ctx, helmOptions: hopts, @@ -103,6 +107,7 @@ func NewCLICluster( noCleanupOnFailure: cfg.NoCleanupOnFailure, debugDirectory: cfg.DebugDirectory, logger: logger, + cli: *cli, } } @@ -129,7 +134,7 @@ func (c *CLICluster) Create(t *testing.T) { args = append(args, "-timeout", "15m") args = append(args, "-auto-approve") - out, err := c.runCLI(args) + out, err := c.cli.Run(args...) if err != nil { c.logger.Logf(t, "error running command `consul-k8s %s`: %s", strings.Join(args, " "), err.Error()) c.logger.Logf(t, "command stdout: %s", string(out)) @@ -162,7 +167,7 @@ func (c *CLICluster) Upgrade(t *testing.T, helmValues map[string]string) { args = append(args, "-timeout", "15m") args = append(args, "-auto-approve") - out, err := c.runCLI(args) + out, err := c.cli.Run(args...) if err != nil { c.logger.Logf(t, "error running command `consul-k8s %s`: %s", strings.Join(args, " "), err.Error()) c.logger.Logf(t, "command stdout: %s", string(out)) @@ -186,7 +191,7 @@ func (c *CLICluster) Destroy(t *testing.T) { // Use `go run` so that the CLI is recompiled and therefore uses the local // charts directory rather than the directory from whenever it was last // compiled. - out, err := c.runCLI(args) + out, err := c.cli.Run(args...) if err != nil { c.logger.Logf(t, "error running command `consul-k8s %s`: %s", strings.Join(args, " "), err.Error()) c.logger.Logf(t, "command stdout: %s", string(out)) @@ -267,6 +272,10 @@ func (c *CLICluster) SetupConsulClient(t *testing.T, secure bool) (*api.Client, return consulClient, config.Address } +func (c *CLICluster) CLI() cli.CLI { + return c.cli +} + func createOrUpdateNamespace(t *testing.T, client kubernetes.Interface, namespace string) { _, err := client.CoreV1().Namespaces().Get(context.Background(), namespace, metav1.GetOptions{}) if errors.IsNotFound(err) { @@ -296,12 +305,3 @@ func (c *CLICluster) setKube(args []string) []string { return args } - -// runCLI runs the CLI with the given args. -// Use `go run` so that the CLI is recompiled and therefore uses the local -// charts directory rather than the directory from whenever it was last compiled. -func (c *CLICluster) runCLI(args []string) ([]byte, error) { - cmd := exec.Command("go", append([]string{"run", "."}, args...)...) - cmd.Dir = config.CLIPath - return cmd.Output() -} diff --git a/acceptance/tests/connect/connect_inject_test.go b/acceptance/tests/connect/connect_inject_test.go index 73ae61c352..5cba67f045 100644 --- a/acceptance/tests/connect/connect_inject_test.go +++ b/acceptance/tests/connect/connect_inject_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/hashicorp/consul-k8s/acceptance/framework/cli" "github.com/hashicorp/consul-k8s/acceptance/framework/consul" "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" @@ -18,6 +19,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +const ipv4RegEx = "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" + // TestConnectInject tests that Connect works in a default and a secure installation. func TestConnectInject(t *testing.T) { cases := map[string]struct { @@ -60,6 +63,9 @@ func TestConnectInject(t *testing.T) { for name, c := range cases { t.Run(name, func(t *testing.T) { + cli, err := cli.NewCLI() + require.NoError(t, err) + cfg := suite.Config() ctx := suite.Environment().DefaultContext(t) @@ -80,6 +86,40 @@ func TestConnectInject(t *testing.T) { connHelper.TestConnectionFailureWithoutIntention(t) connHelper.CreateIntention(t) } + + // Run proxy list and get the two results. + listOut, err := cli.Run("proxy", "list") + require.NoError(t, err) + logger.Log(t, string(listOut)) + list := translateListOutput(listOut) + require.Equal(t, 2, len(list)) + for _, proxyType := range list { + require.Equal(t, "Sidecar", proxyType) + } + + // Run proxy read and check that the connection is present in the output. + retrier := &retry.Timer{Timeout: 160 * time.Second, Wait: 2 * time.Second} + retry.RunWith(retrier, t, func(r *retry.R) { + for podName := range list { + out, err := cli.Run("proxy", "read", podName) + require.NoError(t, err) + + output := string(out) + logger.Log(t, output) + + // Both proxies must see their own local agent and app as clusters. + require.Regexp(r, "local_agent.*STATIC", output) + require.Regexp(r, "local_app.*STATIC", output) + + // Static Client must have Static Server as a cluster and endpoint. + if strings.Contains(podName, "static-client") { + require.Regexp(r, "static-server.*static-server\\.default\\.dc1\\.internal.*EDS", output) + require.Regexp(r, ipv4RegEx+".*static-server.default.dc1.internal", output) + } + + } + }) + connHelper.TestConnectionSuccess(t) connHelper.TestConnectionFailureWhenUnhealthy(t) }) @@ -428,3 +468,22 @@ func TestConnectInject_MultiportServices(t *testing.T) { }) } } + +// translateListOutput takes the raw output from the proxy list command and +// translates the table into a map. +func translateListOutput(raw []byte) map[string]string { + formatted := make(map[string]string) + for _, pod := range strings.Split(strings.TrimSpace(string(raw)), "\n")[3:] { + row := strings.Split(strings.TrimSpace(pod), "\t") + + var name string + if len(row) == 3 { // Handle the case where namespace is present + name = fmt.Sprintf("%s/%s", strings.TrimSpace(row[0]), strings.TrimSpace(row[1])) + } else if len(row) == 2 { + name = strings.TrimSpace(row[0]) + } + formatted[name] = row[len(row)-1] + } + + return formatted +} diff --git a/cli/cmd/install/install.go b/cli/cmd/install/install.go index 0255a9ad21..3329c6fc58 100644 --- a/cli/cmd/install/install.go +++ b/cli/cmd/install/install.go @@ -172,9 +172,6 @@ func (c *Command) init() { }) c.help = c.set.Help() - - // c.Init() calls the embedded BaseCommand's initialization function. - c.Init() } // Run installs Consul into a Kubernetes cluster. diff --git a/cli/cmd/proxy/command.go b/cli/cmd/proxy/command.go new file mode 100644 index 0000000000..663893de5e --- /dev/null +++ b/cli/cmd/proxy/command.go @@ -0,0 +1,26 @@ +package proxy + +import ( + "fmt" + + "github.com/hashicorp/consul-k8s/cli/common" + "github.com/mitchellh/cli" +) + +// ProxyCommand provides a synopsis for the proxy subcommands (e.g. read). +type ProxyCommand struct { + *common.BaseCommand +} + +// Run prints out information about the subcommands. +func (c *ProxyCommand) Run(args []string) int { + return cli.RunResultHelp +} + +func (c *ProxyCommand) Help() string { + return fmt.Sprintf("%s\n\nUsage: consul-k8s proxy ", c.Synopsis()) +} + +func (c *ProxyCommand) Synopsis() string { + return "Inspect Envoy proxies managed by Consul." +} diff --git a/cli/cmd/proxy/list/command.go b/cli/cmd/proxy/list/command.go new file mode 100644 index 0000000000..4389eec0db --- /dev/null +++ b/cli/cmd/proxy/list/command.go @@ -0,0 +1,228 @@ +package list + +import ( + "errors" + "fmt" + "strings" + "sync" + + "github.com/hashicorp/consul-k8s/cli/common" + "github.com/hashicorp/consul-k8s/cli/common/flag" + "github.com/hashicorp/consul-k8s/cli/common/terminal" + helmCLI "helm.sh/helm/v3/pkg/cli" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/validation" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// ListCommand is the command struct for the proxy list command. +type ListCommand struct { + *common.BaseCommand + + kubernetes kubernetes.Interface + namespace string + + set *flag.Sets + + flagNamespace string + flagAllNamespaces bool + + flagKubeConfig string + flagKubeContext string + + once sync.Once + help string +} + +// init sets up flags and help text for the command. +func (c *ListCommand) init() { + c.set = flag.NewSets() + + f := c.set.NewSet("Command Options") + f.StringVar(&flag.StringVar{ + Name: "namespace", + Target: &c.flagNamespace, + Usage: "The namespace to list proxies in.", + Aliases: []string{"n"}, + }) + f.BoolVar(&flag.BoolVar{ + Name: "all-namespaces", + Target: &c.flagAllNamespaces, + Default: false, + Usage: "List pods in all namespaces.", + Aliases: []string{"A"}, + }) + + f = c.set.NewSet("Global Options") + f.StringVar(&flag.StringVar{ + Name: "kubeconfig", + Aliases: []string{"c"}, + Target: &c.flagKubeConfig, + Default: "", + Usage: "Set the path to kubeconfig file.", + }) + f.StringVar(&flag.StringVar{ + Name: "context", + Target: &c.flagKubeContext, + Default: "", + Usage: "Set the Kubernetes context to use.", + }) + + c.help = c.set.Help() +} + +// Run executes the list command. +func (c *ListCommand) Run(args []string) int { + c.once.Do(c.init) + c.Log.ResetNamed("list") + defer common.CloseWithError(c.BaseCommand) + + // Parse the command line flags. + if err := c.set.Parse(args); err != nil { + c.UI.Output("Error parsing arguments: %v", err.Error(), terminal.WithErrorStyle()) + return 1 + } + + // Validate the command line flags. + if err := c.validateFlags(); err != nil { + c.UI.Output("Invalid argument: %v", err.Error(), terminal.WithErrorStyle()) + return 1 + } + + if c.kubernetes == nil { + if err := c.initKubernetes(); err != nil { + c.UI.Output("Error initializing Kubernetes client", err.Error(), terminal.WithErrorStyle()) + return 1 + } + } + + pods, err := c.fetchPods() + if err != nil { + c.UI.Output("Error fetching pods:", err.Error(), terminal.WithErrorStyle()) + return 1 + } + + c.output(pods) + return 0 +} + +// Help returns a description of the command and how it is used. +func (c *ListCommand) Help() string { + c.once.Do(c.init) + return fmt.Sprintf("%s\n\nUsage: consul-k8s proxy list [flags]\n\n%s", c.Synopsis(), c.help) +} + +// Synopsis returns a one-line command summary. +func (c *ListCommand) Synopsis() string { + return "List all Pods running proxies managed by Consul." +} + +// validateFlags ensures that the flags passed in by the can be used. +func (c *ListCommand) validateFlags() error { + if len(c.set.Args()) > 0 { + return errors.New("should have no non-flag arguments") + } + if errs := validation.ValidateNamespaceName(c.flagNamespace, false); c.flagNamespace != "" && len(errs) > 0 { + return fmt.Errorf("invalid namespace name passed for -namespace/-n: %v", strings.Join(errs, "; ")) + } + return nil +} + +// initKubernetes initializes the Kubernetes client and sets the namespace based +// on the user-provided arguments. +func (c *ListCommand) initKubernetes() error { + settings := helmCLI.New() + + restConfig, err := settings.RESTClientGetter().ToRESTConfig() + if err != nil { + return fmt.Errorf("error retrieving Kubernetes authentication %v", err) + } + if c.kubernetes, err = kubernetes.NewForConfig(restConfig); err != nil { + return fmt.Errorf("error creating Kubernetes client %v", err) + } + + if c.flagAllNamespaces { + c.namespace = "" // An empty namespace means all namespaces. + } else if c.flagNamespace != "" { + c.namespace = c.flagNamespace + } else { + c.namespace = settings.Namespace() + } + + return err +} + +// fetchPods fetches all pods in flagNamespace which run Consul proxies. +func (c *ListCommand) fetchPods() ([]v1.Pod, error) { + var pods []v1.Pod + + // Fetch all pods in the namespace with labels matching the gateway component names. + gatewaypods, err := c.kubernetes.CoreV1().Pods(c.namespace).List(c.Ctx, metav1.ListOptions{ + LabelSelector: "component in (ingress-gateway, mesh-gateway, terminating-gateway), chart=consul-helm", + }) + if err != nil { + return nil, err + } + pods = append(pods, gatewaypods.Items...) + + // Fetch all pods in the namespace with a label indicating they are an API gateway. + apigatewaypods, err := c.kubernetes.CoreV1().Pods(c.namespace).List(c.Ctx, metav1.ListOptions{ + LabelSelector: "api-gateway.consul.hashicorp.com/managed=true", + }) + if err != nil { + return nil, err + } + pods = append(pods, apigatewaypods.Items...) + + // Fetch all pods in the namespace with a label indicating they are a service networked by Consul. + sidecarpods, err := c.kubernetes.CoreV1().Pods(c.namespace).List(c.Ctx, metav1.ListOptions{ + LabelSelector: "consul.hashicorp.com/connect-inject-status=injected", + }) + if err != nil { + return nil, err + } + pods = append(pods, sidecarpods.Items...) + + return pods, nil +} + +// output prints a table of pods to the terminal. +func (c *ListCommand) output(pods []v1.Pod) { + if c.flagAllNamespaces { + c.UI.Output("Namespace: All Namespaces\n") + } else if c.namespace != "" { + c.UI.Output("Namespace: %s\n", c.namespace) + } + + var tbl *terminal.Table + if c.flagAllNamespaces { + tbl = terminal.NewTable("Namespace", "Name", "Type") + } else { + tbl = terminal.NewTable("Name", "Type") + } + + for _, pod := range pods { + var proxyType string + switch pod.Labels["component"] { + case "ingress-gateway": + proxyType = "Ingress Gateway" + case "mesh-gateway": + proxyType = "Mesh Gateway" + case "terminating-gateway": + proxyType = "Terminating Gateway" + case "api-gateway": + proxyType = "API Gateway" + default: + proxyType = "Sidecar" + } + + if c.flagAllNamespaces { + tbl.AddRow([]string{pod.Namespace, pod.Name, proxyType}, []string{}) + } else { + tbl.AddRow([]string{pod.Name, proxyType}, []string{}) + } + } + + c.UI.Table(tbl) +} diff --git a/cli/cmd/proxy/list/command_test.go b/cli/cmd/proxy/list/command_test.go new file mode 100644 index 0000000000..f0d552ca7f --- /dev/null +++ b/cli/cmd/proxy/list/command_test.go @@ -0,0 +1,329 @@ +package list + +import ( + "bytes" + "context" + "io" + "os" + "testing" + + "github.com/hashicorp/consul-k8s/cli/common" + "github.com/hashicorp/consul-k8s/cli/common/terminal" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" +) + +func TestFlagParsing(t *testing.T) { + cases := map[string]struct { + args []string + out int + }{ + "No args": { + args: []string{}, + out: 0, + }, + "Nonexistent flag passed, -foo bar": { + args: []string{"-foo", "bar"}, + out: 1, + }, + "Invalid argument passed, -namespace YOLO": { + args: []string{"-namespace", "YOLO"}, + out: 1, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + c := setupCommand(new(bytes.Buffer)) + c.kubernetes = fake.NewSimpleClientset() + out := c.Run(tc.args) + require.Equal(t, tc.out, out) + }) + } +} + +func TestFetchPods(t *testing.T) { + cases := map[string]struct { + namespace string + pods []v1.Pod + expectedPods int + }{ + "No pods": { + namespace: "default", + pods: []v1.Pod{}, + expectedPods: 0, + }, + "Gateway pods": { + namespace: "default", + pods: []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "ingress-gateway", + Namespace: "default", + Labels: map[string]string{ + "component": "ingress-gateway", + "chart": "consul-helm", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "mesh-gateway", + Namespace: "default", + Labels: map[string]string{ + "component": "mesh-gateway", + "chart": "consul-helm", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "terminating-gateway", + Namespace: "default", + Labels: map[string]string{ + "component": "terminating-gateway", + "chart": "consul-helm", + }, + }, + }, + }, + expectedPods: 3, + }, + "API Gateway Pods": { + namespace: "default", + pods: []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "api-gateway", + Namespace: "default", + Labels: map[string]string{ + "api-gateway.consul.hashicorp.com/managed": "true", + }, + }, + }, + }, + expectedPods: 1, + }, + "Sidecar Pods": { + namespace: "default", + pods: []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + Labels: map[string]string{ + "consul.hashicorp.com/connect-inject-status": "injected", + }, + }, + }, + }, + expectedPods: 1, + }, + "All kinds of Pods": { + namespace: "default", + pods: []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + Labels: map[string]string{ + "consul.hashicorp.com/connect-inject-status": "injected", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "mesh-gateway", + Namespace: "default", + Labels: map[string]string{ + "component": "mesh-gateway", + "chart": "consul-helm", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "api-gateway", + Namespace: "default", + Labels: map[string]string{ + "api-gateway.consul.hashicorp.com/managed": "true", + }, + }, + }, + }, + expectedPods: 3, + }, + "Pods in multiple namespaces": { + namespace: "", + pods: []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "api-gateway", + Namespace: "consul", + Labels: map[string]string{ + "api-gateway.consul.hashicorp.com/managed": "true", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + Labels: map[string]string{ + "consul.hashicorp.com/connect-inject-status": "injected", + }, + }, + }, + }, + expectedPods: 2, + }, + "Pods which should not be fetched": { + namespace: "default", + pods: []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "dont-fetch", + Namespace: "default", + Labels: map[string]string{}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + Labels: map[string]string{ + "consul.hashicorp.com/connect-inject-status": "injected", + }, + }, + }, + }, + expectedPods: 1, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + c := setupCommand(new(bytes.Buffer)) + c.kubernetes = fake.NewSimpleClientset(&v1.PodList{Items: tc.pods}) + c.flagNamespace = tc.namespace + + pods, err := c.fetchPods() + + require.NoError(t, err) + require.Equal(t, tc.expectedPods, len(pods)) + }) + } +} + +func TestListCommandOutput(t *testing.T) { + // These regular expressions must be present in the output. + expected := []string{ + "Namespace.*Name.*Type", + "consul.*mesh-gateway.*Mesh Gateway", + "consul.*terminating-gateway.*Terminating Gateway", + "default.*ingress-gateway.*Ingress Gateway", + "consul.*api-gateway.*Sidecar", + "default.*pod1.*Sidecar", + } + notExpected := []string{ + "default.*dont-fetch.*Sidecar", + } + + pods := []v1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "ingress-gateway", + Namespace: "default", + Labels: map[string]string{ + "component": "ingress-gateway", + "chart": "consul-helm", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "mesh-gateway", + Namespace: "consul", + Labels: map[string]string{ + "component": "mesh-gateway", + "chart": "consul-helm", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "terminating-gateway", + Namespace: "consul", + Labels: map[string]string{ + "component": "terminating-gateway", + "chart": "consul-helm", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "api-gateway", + Namespace: "consul", + Labels: map[string]string{ + "api-gateway.consul.hashicorp.com/managed": "true", + }, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "dont-fetch", + Namespace: "default", + Labels: map[string]string{}, + }, + }, + { + ObjectMeta: metav1.ObjectMeta{ + Name: "pod1", + Namespace: "default", + Labels: map[string]string{ + "consul.hashicorp.com/connect-inject-status": "injected", + }, + }, + }, + } + client := fake.NewSimpleClientset(&v1.PodList{Items: pods}) + + buf := new(bytes.Buffer) + c := setupCommand(buf) + c.kubernetes = client + + out := c.Run([]string{"-A"}) + require.Equal(t, 0, out) + + actual := buf.String() + + for _, expression := range expected { + require.Regexp(t, expression, actual) + } + for _, expression := range notExpected { + require.NotRegexp(t, expression, actual) + } +} + +func setupCommand(buf io.Writer) *ListCommand { + // Log at a test level to standard out. + log := hclog.New(&hclog.LoggerOptions{ + Name: "test", + Level: hclog.Debug, + Output: os.Stdout, + }) + + // Setup and initialize the command struct + command := &ListCommand{ + BaseCommand: &common.BaseCommand{ + Log: log, + UI: terminal.NewUI(context.Background(), buf), + }, + } + command.init() + + return command +} diff --git a/cli/cmd/proxy/read/command.go b/cli/cmd/proxy/read/command.go new file mode 100644 index 0000000000..227adbfee9 --- /dev/null +++ b/cli/cmd/proxy/read/command.go @@ -0,0 +1,464 @@ +package read + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "sync" + + "github.com/hashicorp/consul-k8s/cli/common" + "github.com/hashicorp/consul-k8s/cli/common/flag" + "github.com/hashicorp/consul-k8s/cli/common/terminal" + helmCLI "helm.sh/helm/v3/pkg/cli" + "k8s.io/apimachinery/pkg/api/validation" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/utils/strings/slices" +) + +// defaultAdminPort is the port where the Envoy admin API is exposed. +const defaultAdminPort int = 19000 + +const ( + Table = "table" + JSON = "json" + Raw = "raw" +) + +type ReadCommand struct { + *common.BaseCommand + + kubernetes kubernetes.Interface + + set *flag.Sets + + // Command Flags + flagNamespace string + flagPodName string + flagOutput string + + // Output Filtering Opts + flagClusters bool + flagListeners bool + flagRoutes bool + flagEndpoints bool + flagSecrets bool + flagFQDN string + flagAddress string + flagPort int + + // Global Flags + flagKubeConfig string + flagKubeContext string + + fetchConfig func(context.Context, common.PortForwarder) (*EnvoyConfig, error) + + restConfig *rest.Config + + once sync.Once + help string +} + +func (c *ReadCommand) init() { + if c.fetchConfig == nil { + c.fetchConfig = FetchConfig + } + + c.set = flag.NewSets() + f := c.set.NewSet("Command Options") + f.StringVar(&flag.StringVar{ + Name: "namespace", + Target: &c.flagNamespace, + Usage: "The namespace where the target Pod can be found.", + Aliases: []string{"n"}, + }) + f.StringVar(&flag.StringVar{ + Name: "output", + Target: &c.flagOutput, + Usage: "Output the Envoy configuration as 'table', 'json', or 'raw'.", + Default: Table, + Aliases: []string{"o"}, + }) + + f = c.set.NewSet("Output Filtering Options") + f.BoolVar(&flag.BoolVar{ + Name: "clusters", + Target: &c.flagClusters, + Usage: "Filter output to only show clusters.", + }) + f.BoolVar(&flag.BoolVar{ + Name: "listeners", + Target: &c.flagListeners, + Usage: "Filter output to only show listeners.", + }) + f.BoolVar(&flag.BoolVar{ + Name: "routes", + Target: &c.flagRoutes, + Usage: "Filter output to only show routes.", + }) + f.BoolVar(&flag.BoolVar{ + Name: "endpoints", + Target: &c.flagEndpoints, + Usage: "Filter output to only show endpoints.", + }) + f.BoolVar(&flag.BoolVar{ + Name: "secrets", + Target: &c.flagSecrets, + Usage: "Filter output to only show secrets.", + }) + f.StringVar(&flag.StringVar{ + Name: "fqdn", + Target: &c.flagFQDN, + Usage: "Filter cluster output to clusters with a fully qualified domain name which contains the given value. May be combined with -address and -port.", + }) + f.StringVar(&flag.StringVar{ + Name: "address", + Target: &c.flagAddress, + Usage: "Filter clusters, endpoints, and listeners output to those with addresses which contain the given value. May be combined with -fqdn and -port", + }) + f.IntVar(&flag.IntVar{ + Name: "port", + Target: &c.flagPort, + Usage: "Filter endpoints and listeners output to addresses with the given port number. May be combined with -fqdn and -address.", + Default: -1, + }) + + f = c.set.NewSet("GlobalOptions") + f.StringVar(&flag.StringVar{ + Name: "kubeconfig", + Aliases: []string{"c"}, + Target: &c.flagKubeConfig, + Usage: "Set the path to kubeconfig file.", + }) + f.StringVar(&flag.StringVar{ + Name: "context", + Target: &c.flagKubeContext, + Usage: "Set the Kubernetes context to use.", + }) + + c.help = c.set.Help() +} + +func (c *ReadCommand) Run(args []string) int { + c.once.Do(c.init) + c.Log.ResetNamed("read") + defer common.CloseWithError(c.BaseCommand) + + if err := c.parseFlags(args); err != nil { + c.UI.Output(err.Error(), terminal.WithErrorStyle()) + c.UI.Output("\n" + c.Help()) + return 1 + } + + if err := c.validateFlags(); err != nil { + c.UI.Output(err.Error(), terminal.WithErrorStyle()) + c.UI.Output("\n" + c.Help()) + return 1 + } + + if err := c.initKubernetes(); err != nil { + c.UI.Output(err.Error(), terminal.WithErrorStyle()) + return 1 + } + + adminPorts, err := c.fetchAdminPorts() + if err != nil { + c.UI.Output(err.Error(), terminal.WithErrorStyle()) + return 1 + } + + configs, err := c.fetchConfigs(adminPorts) + if err != nil { + c.UI.Output(err.Error(), terminal.WithErrorStyle()) + return 1 + } + + err = c.outputConfigs(configs) + if err != nil { + c.UI.Output(err.Error(), terminal.WithErrorStyle()) + return 1 + } + + return 0 +} + +func (c *ReadCommand) Help() string { + c.once.Do(c.init) + return fmt.Sprintf("%s\n\nUsage: consul-k8s proxy read [flags]\n\n%s", c.Synopsis(), c.help) +} + +func (c *ReadCommand) Synopsis() string { + return "Inspect the Envoy configuration for a given Pod." +} + +func (c *ReadCommand) parseFlags(args []string) error { + // Separate positional arguments from keyed arguments. + positional := []string{} + for _, arg := range args { + if strings.HasPrefix(arg, "-") { + break + } + positional = append(positional, arg) + } + keyed := args[len(positional):] + + if len(positional) != 1 { + return fmt.Errorf("Exactly one positional argument is required: ") + } + c.flagPodName = positional[0] + + if err := c.set.Parse(keyed); err != nil { + return err + } + + return nil +} + +func (c *ReadCommand) validateFlags() error { + if errs := validation.ValidateNamespaceName(c.flagNamespace, false); c.flagNamespace != "" && len(errs) > 0 { + return fmt.Errorf("invalid namespace name passed for -namespace/-n: %v", strings.Join(errs, "; ")) + } + if outputs := []string{Table, JSON, Raw}; !slices.Contains(outputs, c.flagOutput) { + return fmt.Errorf("-output must be one of %s.", strings.Join(outputs, ", ")) + } + return nil +} + +func (c *ReadCommand) initKubernetes() (err error) { + settings := helmCLI.New() + + if c.flagKubeConfig == "" { + settings.KubeConfig = c.flagKubeConfig + } + + if c.flagKubeContext == "" { + settings.KubeContext = c.flagKubeContext + } + + if c.restConfig == nil { + if c.restConfig, err = settings.RESTClientGetter().ToRESTConfig(); err != nil { + return fmt.Errorf("error creating Kubernetes REST config %v", err) + } + } + + if c.kubernetes == nil { + if c.kubernetes, err = kubernetes.NewForConfig(c.restConfig); err != nil { + return fmt.Errorf("error creating Kubernetes client %v", err) + } + } + + if c.flagNamespace == "" { + c.flagNamespace = settings.Namespace() + } + + return nil +} + +func (c *ReadCommand) fetchAdminPorts() (map[string]int, error) { + adminPorts := make(map[string]int, 0) + + pod, err := c.kubernetes.CoreV1().Pods(c.flagNamespace).Get(c.Ctx, c.flagPodName, metav1.GetOptions{}) + if err != nil { + return adminPorts, err + } + + connectService, isMultiport := pod.Annotations["consul.hashicorp.com/connect-service"] + + if !isMultiport { + // Return the default port configuration. + adminPorts[c.flagPodName] = defaultAdminPort + return adminPorts, nil + } + + for index, service := range strings.Split(connectService, ",") { + adminPorts[service] = defaultAdminPort + index + } + + return adminPorts, nil +} + +func (c *ReadCommand) fetchConfigs(adminPorts map[string]int) (map[string]*EnvoyConfig, error) { + configs := make(map[string]*EnvoyConfig, 0) + + for name, adminPort := range adminPorts { + pf := common.PortForward{ + Namespace: c.flagNamespace, + PodName: c.flagPodName, + RemotePort: adminPort, + KubeClient: c.kubernetes, + RestConfig: c.restConfig, + } + + config, err := c.fetchConfig(c.Ctx, &pf) + if err != nil { + return configs, err + } + + configs[name] = config + } + + return configs, nil +} + +func (c *ReadCommand) outputConfigs(configs map[string]*EnvoyConfig) error { + switch c.flagOutput { + case Table: + return c.outputTables(configs) + case JSON: + return c.outputJSON(configs) + case Raw: + return c.outputRaw(configs) + } + + return nil +} + +// shouldPrintTable takes the flag passed in for that table. If the flag is true, +// the table should always be printed. Otherwise, it should only be printed if +// no other table filtering flags are passed in. +func (c *ReadCommand) shouldPrintTable(table bool) bool { + if table { + return table + } + + // True if no other table filtering flags are passed in. + return !(c.flagClusters || c.flagEndpoints || c.flagListeners || c.flagRoutes || c.flagSecrets) +} + +func (c *ReadCommand) outputTables(configs map[string]*EnvoyConfig) error { + if c.flagFQDN != "" || c.flagAddress != "" || c.flagPort != -1 { + c.UI.Output("Filters applied", terminal.WithHeaderStyle()) + + if c.flagFQDN != "" { + c.UI.Output(fmt.Sprintf("Fully qualified domain names containing: %s", c.flagFQDN), terminal.WithInfoStyle()) + } + if c.flagAddress != "" { + c.UI.Output(fmt.Sprintf("Endpoint addresses containing: %s", c.flagAddress), terminal.WithInfoStyle()) + } + if c.flagPort != -1 { + c.UI.Output(fmt.Sprintf("Endpoint addresses with port number: %d", c.flagPort), terminal.WithInfoStyle()) + } + + c.UI.Output("") + } + + for name, config := range configs { + c.UI.Output(fmt.Sprintf("Envoy configuration for %s in namespace %s:", name, c.flagNamespace)) + + c.outputClustersTable(FilterClusters(config.Clusters, c.flagFQDN, c.flagAddress, c.flagPort)) + c.outputEndpointsTable(FilterEndpoints(config.Endpoints, c.flagAddress, c.flagPort)) + c.outputListenersTable(FilterListeners(config.Listeners, c.flagAddress, c.flagPort)) + c.outputRoutesTable(config.Routes) + c.outputSecretsTable(config.Secrets) + c.UI.Output("\n") + } + + return nil +} + +func (c *ReadCommand) outputJSON(configs map[string]*EnvoyConfig) error { + cfgs := make(map[string]interface{}) + for name, config := range configs { + cfg := make(map[string]interface{}) + if c.shouldPrintTable(c.flagClusters) { + cfg["clusters"] = FilterClusters(config.Clusters, c.flagFQDN, c.flagAddress, c.flagPort) + } + if c.shouldPrintTable(c.flagEndpoints) { + cfg["endpoints"] = FilterEndpoints(config.Endpoints, c.flagAddress, c.flagPort) + } + if c.shouldPrintTable(c.flagListeners) { + cfg["listeners"] = FilterListeners(config.Listeners, c.flagAddress, c.flagPort) + } + if c.shouldPrintTable(c.flagRoutes) { + cfg["routes"] = config.Routes + } + if c.shouldPrintTable(c.flagSecrets) { + cfg["secrets"] = config.Secrets + } + + cfgs[name] = cfg + } + + out, err := json.MarshalIndent(cfgs, "", "\t") + if err != nil { + return err + } + + c.UI.Output(string(out)) + + return nil +} + +func (c *ReadCommand) outputRaw(configs map[string]*EnvoyConfig) error { + cfgs := make(map[string]interface{}, 0) + for name, config := range configs { + var cfg interface{} + if err := json.Unmarshal(config.rawCfg, &cfg); err != nil { + return err + } + + cfgs[name] = cfg + } + + out, err := json.MarshalIndent(cfgs, "", "\t") + if err != nil { + return err + } + + c.UI.Output(string(out)) + + return nil +} + +func (c *ReadCommand) outputClustersTable(clusters []Cluster) { + if !c.shouldPrintTable(c.flagClusters) { + return + } + + c.UI.Output(fmt.Sprintf("Clusters (%d)", len(clusters)), terminal.WithHeaderStyle()) + table := terminal.NewTable("Name", "FQDN", "Endpoints", "Type", "Last Updated") + for _, cluster := range clusters { + table.AddRow([]string{cluster.Name, cluster.FullyQualifiedDomainName, strings.Join(cluster.Endpoints, ", "), + cluster.Type, cluster.LastUpdated}, []string{}) + } + c.UI.Table(table) + c.UI.Output("") +} + +func (c *ReadCommand) outputEndpointsTable(endpoints []Endpoint) { + if !c.shouldPrintTable(c.flagEndpoints) { + return + } + + c.UI.Output(fmt.Sprintf("Endpoints (%d)", len(endpoints)), terminal.WithHeaderStyle()) + c.UI.Table(formatEndpoints(endpoints)) +} + +func (c *ReadCommand) outputListenersTable(listeners []Listener) { + if !c.shouldPrintTable(c.flagListeners) { + return + } + + c.UI.Output(fmt.Sprintf("Listeners (%d)", len(listeners)), terminal.WithHeaderStyle()) + c.UI.Table(formatListeners(listeners)) +} + +func (c *ReadCommand) outputRoutesTable(routes []Route) { + if !c.shouldPrintTable(c.flagRoutes) { + return + } + + c.UI.Output(fmt.Sprintf("Routes (%d)", len(routes)), terminal.WithHeaderStyle()) + c.UI.Table(formatRoutes(routes)) +} + +func (c *ReadCommand) outputSecretsTable(secrets []Secret) { + if !c.shouldPrintTable(c.flagSecrets) { + return + } + + c.UI.Output(fmt.Sprintf("Secrets (%d)", len(secrets)), terminal.WithHeaderStyle()) + c.UI.Table(formatSecrets(secrets)) +} diff --git a/cli/cmd/proxy/read/command_test.go b/cli/cmd/proxy/read/command_test.go new file mode 100644 index 0000000000..5295484be8 --- /dev/null +++ b/cli/cmd/proxy/read/command_test.go @@ -0,0 +1,167 @@ +package read + +import ( + "bytes" + "context" + "fmt" + "io" + "os" + "testing" + + "github.com/hashicorp/consul-k8s/cli/common" + "github.com/hashicorp/consul-k8s/cli/common/terminal" + "github.com/hashicorp/go-hclog" + "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" +) + +func TestFlagParsing(t *testing.T) { + cases := map[string]struct { + args []string + out int + }{ + "No args": { + args: []string{}, + out: 1, + }, + "Multiple podnames passed": { + args: []string{"podname", "podname2"}, + out: 1, + }, + "Nonexistent flag passed, -foo bar": { + args: []string{"podName", "-foo", "bar"}, + out: 1, + }, + "Invalid argument passed, -namespace YOLO": { + args: []string{"podName", "-namespace", "YOLO"}, + out: 1, + }, + "User passed incorrect output": { + args: []string{"podName", "-output", "image"}, + out: 1, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + c := setupCommand(new(bytes.Buffer)) + c.kubernetes = fake.NewSimpleClientset() + + out := c.Run(tc.args) + require.Equal(t, tc.out, out) + }) + } +} + +func TestReadCommandOutput(t *testing.T) { + podName := "fakePod" + + // These regular expressions must be present in the output. + expectedHeader := fmt.Sprintf("Envoy configuration for %s in namespace default:", podName) + expected := map[string][]string{ + "-clusters": {"==> Clusters \\(6\\)", + "Name.*FQDN.*Endpoints.*Type.*Last Updated", + "local_agent.*local_agent.*192\\.168\\.79\\.187:8502.*STATIC.*2022-05-13T04:22:39\\.553Z", + "local_app.*local_app.*127\\.0\\.0\\.1:8080.*STATIC.*2022-05-13T04:22:39\\.655Z", + "client.*client\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS.*2022-06-09T00:39:12\\.948Z", + "frontend.*frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS.*2022-06-09T00:39:12\\.855Z", + "original-destination.*original-destination.*ORIGINAL_DST.*2022-05-13T04:22:39.743Z", + "server.*server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul.*EDS.*2022-06-09T00:39:12\\.754Z"}, + + "-endpoints": {"==> Endpoints \\(9\\)", + "Address:Port.*Cluster.*Weight.*Status", + "192.168.79.187:8502.*local_agent.*1.00.*HEALTHY", + "127.0.0.1:8080.*local_app.*1.00.*HEALTHY", + "192.168.31.201:20000.*1.00.*HEALTHY", + "192.168.47.235:20000.*1.00.*HEALTHY", + "192.168.71.254:20000.*1.00.*HEALTHY", + "192.168.63.120:20000.*1.00.*HEALTHY", + "192.168.18.110:20000.*1.00.*HEALTHY", + "192.168.52.101:20000.*1.00.*HEALTHY", + "192.168.65.131:20000.*1.00.*HEALTHY"}, + + "-listeners": {"==> Listeners \\(2\\)", + "Name.*Address:Port.*Direction.*Filter Chain Match.*Filters.*Last Updated", + "public_listener.*192\\.168\\.69\\.179:20000.*INBOUND.*Any.*\\* to local_app/.*2022-06-09T00:39:27\\.668Z", + "outbound_listener.*127.0.0.1:15001.*OUTBOUND.*10\\.100\\.134\\.173/32, 240\\.0\\.0\\.3/32.*to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul.*2022-05-24T17:41:59\\.079Z", + "10\\.100\\.254\\.176/32, 240\\.0\\.0\\.4/32.*\\* to server\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul/", + "10\\.100\\.31\\.2/32, 240\\.0\\.0\\.2/32.*to frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul", + "Any.*to original-destination"}, + + "-routes": {"==> Routes \\(2\\)", + "Name.*Destination Cluster.*Last Updated", + "public_listener.*local_app/.*2022-06-09T00:39:27.667Z", + "server.*server\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul/.*2022-05-24T17:41:59\\.078Z"}, + + "-secrets": {"==> Secrets \\(2\\)", + "Name.*Type.*Last Updated", + "default.*Dynamic Active.*2022-05-24T17:41:59.078Z", + "ROOTCA.*Dynamic Warming.*2022-03-15T05:14:22.868Z"}, + } + + cases := map[string][]string{ + "No filters": {}, + "Clusters": {"-clusters"}, + "Endpoints": {"-endpoints"}, + "Listeners": {"-listeners"}, + "Routes": {"-routes"}, + "Secrets": {"-secrets"}, + "Clusters and routes": {"-clusters", "-routes"}, + "Secrets then listeners": {"-secrets", "-listeners"}, + } + + fakePod := v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: "default", + }, + } + + buf := new(bytes.Buffer) + c := setupCommand(buf) + c.kubernetes = fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{fakePod}}) + + // A fetchConfig function that just returns the test Envoy config. + c.fetchConfig = func(context.Context, common.PortForwarder) (*EnvoyConfig, error) { + return testEnvoyConfig, nil + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + args := append([]string{podName}, tc...) + out := c.Run(args) + require.Equal(t, 0, out) + + actual := buf.String() + + require.Regexp(t, expectedHeader, actual) + for _, table := range tc { + for _, expression := range expected[table] { + require.Regexp(t, expression, actual) + } + } + }) + } +} + +func setupCommand(buf io.Writer) *ReadCommand { + // Log at a test level to standard out. + log := hclog.New(&hclog.LoggerOptions{ + Name: "test", + Level: hclog.Debug, + Output: os.Stdout, + }) + + // Setup and initialize the command struct + command := &ReadCommand{ + BaseCommand: &common.BaseCommand{ + Log: log, + UI: terminal.NewUI(context.Background(), buf), + }, + } + command.init() + + return command +} diff --git a/cli/cmd/proxy/read/config.go b/cli/cmd/proxy/read/config.go new file mode 100644 index 0000000000..cc3fa8d7e5 --- /dev/null +++ b/cli/cmd/proxy/read/config.go @@ -0,0 +1,440 @@ +package read + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "github.com/hashicorp/consul-k8s/cli/common" +) + +// EnvoyConfig represents the configuration retrieved from a config dump at the +// admin endpoint. It wraps the Envoy ConfigDump struct to give us convenient +// access to the different sections of the config. +type EnvoyConfig struct { + rawCfg []byte + Clusters []Cluster + Endpoints []Endpoint + Listeners []Listener + Routes []Route + Secrets []Secret +} + +// Cluster represents a cluster in the Envoy config. +type Cluster struct { + Name string + FullyQualifiedDomainName string + Endpoints []string + Type string + LastUpdated string +} + +// Endpoint represents an endpoint in the Envoy config. +type Endpoint struct { + Address string + Cluster string + Weight float64 + Status string +} + +// Listener represents a listener in the Envoy config. +type Listener struct { + Name string + Address string + FilterChain []FilterChain + Direction string + LastUpdated string +} + +type FilterChain struct { + Filters []string + FilterChainMatch string +} + +// Route represents a route in the Envoy config. +type Route struct { + Name string + DestinationCluster string + LastUpdated string +} + +// Secret represents a secret in the Envoy config. +type Secret struct { + Name string + Type string + LastUpdated string +} + +// FetchConfig opens a port forward to the Envoy admin API and fetches the +// configuration from the config dump endpoint. +func FetchConfig(ctx context.Context, portForward common.PortForwarder) (*EnvoyConfig, error) { + endpoint, err := portForward.Open(ctx) + if err != nil { + return nil, err + } + defer portForward.Close() + + // Fetch the config dump + response, err := http.Get(fmt.Sprintf("http://%s/config_dump?include_eds", endpoint)) + if err != nil { + return nil, err + } + configDump, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + if err := response.Body.Close(); err != nil { + return nil, err + } + + // Fetch the clusters mapping + response, err = http.Get(fmt.Sprintf("http://%s/clusters?format=json", endpoint)) + if err != nil { + return nil, err + } + clusters, err := io.ReadAll(response.Body) + if err != nil { + return nil, err + } + if err := response.Body.Close(); err != nil { + return nil, err + } + + config := fmt.Sprintf("{\n\"config_dump\":%s,\n\"clusters\":%s}", string(configDump), string(clusters)) + + envoyConfig := &EnvoyConfig{} + err = json.Unmarshal([]byte(config), envoyConfig) + if err != nil { + return nil, err + } + return envoyConfig, nil +} + +// JSON returns the original JSON Envoy config dump data which was used to create +// the Config object. +func (c *EnvoyConfig) JSON() []byte { + return c.rawCfg +} + +// UnmarshalJSON implements the json.Unmarshaler interface to unmarshal the raw +// config dump bytes into EnvoyConfig. It saves a copy of the original bytes +// which can be fetched with the JSON method. +func (c *EnvoyConfig) UnmarshalJSON(b []byte) error { + // Save the original config dump bytes for marshalling. We should treat this + // struct as immutable so this should be safe. + c.rawCfg = b + + var root root + err := json.Unmarshal(b, &root) + + clusterMapping, endpointMapping := make(map[string][]string), make(map[string]string) + for _, clusterStatus := range root.Clusters.ClusterStatuses { + var addresses []string + for _, status := range clusterStatus.HostStatuses { + address := fmt.Sprintf("%s:%d", status.Address.SocketAddress.Address, int(status.Address.SocketAddress.PortValue)) + addresses = append(addresses, address) + endpointMapping[address] = clusterStatus.Name + } + clusterMapping[clusterStatus.Name] = addresses + } + + // Dispatch each section to the appropriate parsing function by its type. + for _, config := range root.ConfigDump.Configs { + switch config["@type"] { + case "type.googleapis.com/envoy.admin.v3.ClustersConfigDump": + clusters, err := parseClusters(config, clusterMapping) + if err != nil { + return err + } + c.Clusters = clusters + case "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump": + endpoints, err := parseEndpoints(config, endpointMapping) + if err != nil { + return err + } + c.Endpoints = endpoints + case "type.googleapis.com/envoy.admin.v3.ListenersConfigDump": + listeners, err := parseListeners(config) + if err != nil { + return err + } + c.Listeners = listeners + case "type.googleapis.com/envoy.admin.v3.RoutesConfigDump": + routes, err := parseRoutes(config) + if err != nil { + return err + } + c.Routes = routes + case "type.googleapis.com/envoy.admin.v3.SecretsConfigDump": + secrets, err := parseSecrets(config) + if err != nil { + return err + } + c.Secrets = secrets + } + } + + return err +} + +func parseClusters(rawCfg map[string]interface{}, clusterMapping map[string][]string) ([]Cluster, error) { + clusters := make([]Cluster, 0) + + raw, err := json.Marshal(rawCfg) + if err != nil { + return clusters, err + } + + var clustersCD clustersConfigDump + if err = json.Unmarshal(raw, &clustersCD); err != nil { + return clusters, err + } + + for _, cluster := range append(clustersCD.StaticClusters, clustersCD.DynamicActiveClusters...) { + // Join nested endpoint data into a slice of strings. + endpoints := make([]string, 0) + for _, endpoint := range cluster.Cluster.LoadAssignment.Endpoints { + for _, lbEndpoint := range endpoint.LBEndpoints { + endpoints = append(endpoints, fmt.Sprintf("%s:%d", lbEndpoint.Endpoint.Address.SocketAddress.Address, + int(lbEndpoint.Endpoint.Address.SocketAddress.PortValue))) + } + } + + // Add addresses discovered by EDS if not already added + if addresses, ok := clusterMapping[cluster.Cluster.FQDN]; ok { + for _, endpoint := range addresses { + alreadyAdded := false + for _, existingEndpoint := range endpoints { + if existingEndpoint == endpoint { + alreadyAdded = true + break + } + } + if !alreadyAdded { + endpoints = append(endpoints, endpoint) + } + } + } + + clusters = append(clusters, Cluster{ + Name: strings.Split(cluster.Cluster.FQDN, ".")[0], + FullyQualifiedDomainName: cluster.Cluster.FQDN, + Endpoints: endpoints, + Type: cluster.Cluster.ClusterType, + LastUpdated: cluster.LastUpdated, + }) + } + + return clusters, nil +} + +func parseEndpoints(rawCfg map[string]interface{}, endpointMapping map[string]string) ([]Endpoint, error) { + endpoints := make([]Endpoint, 0) + + raw, err := json.Marshal(rawCfg) + if err != nil { + return endpoints, err + } + + var endpointsCD endpointsConfigDump + if err = json.Unmarshal(raw, &endpointsCD); err != nil { + return endpoints, err + } + + for _, endpointConfig := range append(endpointsCD.StaticEndpointConfigs, endpointsCD.DynamicEndpointConfigs...) { + for _, endpoint := range endpointConfig.EndpointConfig.Endpoints { + for _, lbEndpoint := range endpoint.LBEndpoints { + address := fmt.Sprintf("%s:%d", lbEndpoint.Endpoint.Address.SocketAddress.Address, int(lbEndpoint.Endpoint.Address.SocketAddress.PortValue)) + + cluster := endpointConfig.EndpointConfig.Name + // Fill in cluster from EDS endpoint mapping. + if edsCluster, ok := endpointMapping[address]; ok && cluster == "" { + cluster = edsCluster + } + + endpoints = append(endpoints, Endpoint{ + Address: address, + Cluster: cluster, + Weight: lbEndpoint.LoadBalancingWeight, + Status: lbEndpoint.HealthStatus, + }) + } + } + } + + return endpoints, nil +} + +func parseListeners(rawCfg map[string]interface{}) ([]Listener, error) { + listeners := make([]Listener, 0) + + raw, err := json.Marshal(rawCfg) + if err != nil { + return listeners, err + } + + var listenersCD listenersConfigDump + if err = json.Unmarshal(raw, &listenersCD); err != nil { + return listeners, err + } + + listenersConfig := []listenerConfig{} + for _, listener := range listenersCD.DynamicListeners { + listenersConfig = append(listenersConfig, listener.ActiveState) + } + listenersConfig = append(listenersConfig, listenersCD.StaticListeners...) + + for _, listener := range listenersConfig { + address := fmt.Sprintf("%s:%d", listener.Listener.Address.SocketAddress.Address, int(listener.Listener.Address.SocketAddress.PortValue)) + + // Format the filter chain configs into something more readable. + filterChain := []FilterChain{} + for _, chain := range listener.Listener.FilterChains { + filterChainMatch := []string{} + for _, prefixRange := range chain.FilterChainMatch.PrefixRanges { + filterChainMatch = append(filterChainMatch, fmt.Sprintf("%s/%d", prefixRange.AddressPrefix, int(prefixRange.PrefixLen))) + } + if len(filterChainMatch) == 0 { + filterChainMatch = append(filterChainMatch, "Any") + } + + filterChain = append(filterChain, FilterChain{ + FilterChainMatch: strings.Join(filterChainMatch, ", "), + Filters: formatFilters(chain), + }) + } + + direction := "UNSPECIFIED" + if listener.Listener.TrafficDirection != "" { + direction = listener.Listener.TrafficDirection + } + + listeners = append(listeners, Listener{ + Name: strings.Split(listener.Listener.Name, ":")[0], + Address: address, + FilterChain: filterChain, + Direction: direction, + LastUpdated: listener.LastUpdated, + }) + } + + return listeners, nil +} + +func parseRoutes(rawCfg map[string]interface{}) ([]Route, error) { + routes := make([]Route, 0) + + raw, err := json.Marshal(rawCfg) + if err != nil { + return routes, err + } + + var routesCD routesConfigDump + if err = json.Unmarshal(raw, &routesCD); err != nil { + return routes, err + } + + for _, route := range routesCD.StaticRouteConfigs { + destinationClusters := []string{} + for _, host := range route.RouteConfig.VirtualHosts { + for _, routeCfg := range host.Routes { + destinationClusters = append(destinationClusters, + fmt.Sprintf("%s%s", routeCfg.Route.Cluster, routeCfg.Match.Prefix)) + } + } + + routes = append(routes, Route{ + Name: route.RouteConfig.Name, + DestinationCluster: strings.Join(destinationClusters, ", "), + LastUpdated: route.LastUpdated, + }) + } + + return routes, nil +} + +func parseSecrets(rawCfg map[string]interface{}) ([]Secret, error) { + secrets := make([]Secret, 0) + + raw, err := json.Marshal(rawCfg) + if err != nil { + return secrets, err + } + + var secretsCD secretsConfigDump + if err = json.Unmarshal(raw, &secretsCD); err != nil { + return secrets, err + } + + for _, secret := range secretsCD.StaticSecrets { + secrets = append(secrets, Secret{ + Name: secret.Name, + Type: "Static", + LastUpdated: secret.LastUpdated, + }) + } + + for _, secret := range secretsCD.DynamicActiveSecrets { + secrets = append(secrets, Secret{ + Name: secret.Name, + Type: "Dynamic Active", + LastUpdated: secret.LastUpdated, + }) + } + + for _, secret := range secretsCD.DynamicWarmingSecrets { + secrets = append(secrets, Secret{ + Name: secret.Name, + Type: "Dynamic Warming", + LastUpdated: secret.LastUpdated, + }) + } + + return secrets, nil +} + +func formatFilters(filterChain filterChain) (filters []string) { + // Filters can have many custom configurations, each must be handled differently. + formatters := map[string]func(typedConfig) string{ + "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC": formatFilterRBAC, + "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy": formatFilterTCPProxy, + "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager": formatFilterHTTPConnectionManager, + } + + for _, chainFilter := range filterChain.Filters { + if formatter, ok := formatters[chainFilter.TypedConfig.Type]; ok { + filters = append(filters, formatter(chainFilter.TypedConfig)) + } + } + return +} + +func formatFilterTCPProxy(config typedConfig) (filter string) { + return "to " + config.Cluster +} + +func formatFilterRBAC(cfg typedConfig) (filter string) { + action := cfg.Rules.Action + for _, principal := range cfg.Rules.Policies.ConsulIntentions.Principals { + regex := principal.Authenticated.PrincipalName.SafeRegex.Regex + filter += fmt.Sprintf("%s %s", action, regex) + } + return +} + +func formatFilterHTTPConnectionManager(cfg typedConfig) (filter string) { + for _, host := range cfg.RouteConfig.VirtualHosts { + filter += strings.Join(host.Domains, ", ") + filter += " to " + + routes := "" + for _, route := range host.Routes { + routes += fmt.Sprintf("%s%s", route.Route.Cluster, route.Match.Prefix) + } + filter += routes + } + return +} diff --git a/cli/cmd/proxy/read/config_test.go b/cli/cmd/proxy/read/config_test.go new file mode 100644 index 0000000000..cce3c4c12a --- /dev/null +++ b/cli/cmd/proxy/read/config_test.go @@ -0,0 +1,261 @@ +package read + +import ( + "bytes" + "context" + "embed" + "encoding/json" + "fmt" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +//go:embed test_config_dump.json test_clusters.json +var fs embed.FS + +const ( + testConfigDump = "test_config_dump.json" + testClusters = "test_clusters.json" +) + +func TestUnmarshaling(t *testing.T) { + var envoyConfig EnvoyConfig + err := json.Unmarshal(rawEnvoyConfig(t), &envoyConfig) + require.NoError(t, err) + + require.Equal(t, testEnvoyConfig.Clusters, envoyConfig.Clusters) + require.Equal(t, testEnvoyConfig.Endpoints, envoyConfig.Endpoints) + require.Equal(t, testEnvoyConfig.Listeners, envoyConfig.Listeners) + require.Equal(t, testEnvoyConfig.Routes, envoyConfig.Routes) + require.Equal(t, testEnvoyConfig.Secrets, envoyConfig.Secrets) +} + +func TestJSON(t *testing.T) { + raw, err := fs.ReadFile(testConfigDump) + require.NoError(t, err) + expected := bytes.TrimSpace(raw) + + var envoyConfig EnvoyConfig + err = json.Unmarshal(raw, &envoyConfig) + require.NoError(t, err) + + actual := envoyConfig.JSON() + + require.Equal(t, expected, actual) +} + +func TestFetchConfig(t *testing.T) { + configDump, err := fs.ReadFile(testConfigDump) + require.NoError(t, err) + + clusters, err := fs.ReadFile(testClusters) + require.NoError(t, err) + + mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/config_dump" { + w.Write(configDump) + } + if r.URL.Path == "/clusters" { + w.Write(clusters) + } + })) + defer mockServer.Close() + + mpf := &mockPortForwarder{ + openBehavior: func(ctx context.Context) (string, error) { + return strings.Replace(mockServer.URL, "http://", "", 1), nil + }, + } + + envoyConfig, err := FetchConfig(context.Background(), mpf) + + require.NoError(t, err) + + require.Equal(t, testEnvoyConfig.Clusters, envoyConfig.Clusters) + require.Equal(t, testEnvoyConfig.Endpoints, envoyConfig.Endpoints) + require.Equal(t, testEnvoyConfig.Listeners, envoyConfig.Listeners) + require.Equal(t, testEnvoyConfig.Routes, envoyConfig.Routes) + require.Equal(t, testEnvoyConfig.Secrets, envoyConfig.Secrets) +} + +type mockPortForwarder struct { + openBehavior func(context.Context) (string, error) +} + +func (m *mockPortForwarder) Open(ctx context.Context) (string, error) { return m.openBehavior(ctx) } +func (m *mockPortForwarder) Close() {} + +func rawEnvoyConfig(t *testing.T) []byte { + configDump, err := fs.ReadFile(testConfigDump) + require.NoError(t, err) + + clusters, err := fs.ReadFile(testClusters) + require.NoError(t, err) + + return []byte(fmt.Sprintf("{\n\"config_dump\":%s,\n\"clusters\":%s}", string(configDump), string(clusters))) +} + +// testEnvoyConfig is what we expect the config at `test_config_dump.json` to be. +var testEnvoyConfig = &EnvoyConfig{ + Clusters: []Cluster{ + { + Name: "local_agent", + FullyQualifiedDomainName: "local_agent", + Endpoints: []string{"192.168.79.187:8502", "172.18.0.2:8502"}, + Type: "STATIC", + LastUpdated: "2022-05-13T04:22:39.553Z", + }, + { + Name: "client", + FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + Type: "EDS", + LastUpdated: "2022-06-09T00:39:12.948Z", + }, + { + Name: "frontend", + FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + Type: "EDS", + LastUpdated: "2022-06-09T00:39:12.855Z", + }, + { + Name: "local_app", + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080", "127.0.0.1:0"}, + Type: "STATIC", + LastUpdated: "2022-05-13T04:22:39.655Z", + }, + { + Name: "original-destination", + FullyQualifiedDomainName: "original-destination", + Endpoints: []string{}, + Type: "ORIGINAL_DST", + LastUpdated: "2022-05-13T04:22:39.743Z", + }, + { + Name: "server", + FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + Type: "EDS", + LastUpdated: "2022-06-09T00:39:12.754Z", + }, + }, + Endpoints: []Endpoint{ + { + Address: "192.168.79.187:8502", + Cluster: "local_agent", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "127.0.0.1:8080", + Cluster: "local_app", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.31.201:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.47.235:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.71.254:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.63.120:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.18.110:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.52.101:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.65.131:20000", + Weight: 1, + Status: "HEALTHY", + }, + }, + Listeners: []Listener{ + { + Name: "public_listener", + Address: "192.168.69.179:20000", + FilterChain: []FilterChain{ + { + FilterChainMatch: "Any", + Filters: []string{"* to local_app/"}, + }, + }, + Direction: "INBOUND", + LastUpdated: "2022-06-09T00:39:27.668Z", + }, + { + Name: "outbound_listener", + Address: "127.0.0.1:15001", + FilterChain: []FilterChain{ + { + FilterChainMatch: "10.100.134.173/32, 240.0.0.3/32", + Filters: []string{"to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, + }, + { + FilterChainMatch: "10.100.254.176/32, 240.0.0.4/32", + Filters: []string{"* to server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/"}, + }, + { + FilterChainMatch: "10.100.31.2/32, 240.0.0.2/32", + Filters: []string{ + "to frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + }, + }, + { + FilterChainMatch: "Any", + Filters: []string{"to original-destination"}, + }, + }, + Direction: "OUTBOUND", + LastUpdated: "2022-05-24T17:41:59.079Z", + }, + }, + Routes: []Route{ + { + Name: "public_listener", + DestinationCluster: "local_app/", + LastUpdated: "2022-06-09T00:39:27.667Z", + }, + { + Name: "server", + DestinationCluster: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/", + LastUpdated: "2022-05-24T17:41:59.078Z", + }, + }, + Secrets: []Secret{ + { + Name: "default", + Type: "Dynamic Active", + LastUpdated: "2022-05-24T17:41:59.078Z", + }, + { + Name: "ROOTCA", + Type: "Dynamic Warming", + LastUpdated: "2022-03-15T05:14:22.868Z", + }, + }, +} diff --git a/cli/cmd/proxy/read/envoy_types.go b/cli/cmd/proxy/read/envoy_types.go new file mode 100644 index 0000000000..10f76101dd --- /dev/null +++ b/cli/cmd/proxy/read/envoy_types.go @@ -0,0 +1,269 @@ +package read + +/* Envoy Types +These types are based on the JSON returned from the Envoy Config Dump API on the +admin interface. They are a subset of what is returned from that API to support +unmarshaling in the ConfigDump struct. +Please refer to the Envoy config dump documentation when modifying or extending: +https://www.envoyproxy.io/docs/envoy/latest/api-v3/admin/v3/config_dump.proto +*/ + +type root struct { + ConfigDump configDump `json:"config_dump"` + Clusters clusters `json:"clusters"` +} + +type configDump struct { + Configs []map[string]interface{} `json:"configs"` +} + +type clustersConfigDump struct { + ConfigType string `json:"@type"` + StaticClusters []clusterConfig `json:"static_clusters"` + DynamicActiveClusters []clusterConfig `json:"dynamic_active_clusters"` +} + +type clusterConfig struct { + Cluster clusterMeta `json:"cluster"` + LastUpdated string `json:"last_updated"` +} + +type clusterMeta struct { + FQDN string `json:"name"` + ClusterType string `json:"type"` + LoadAssignment loadAssignment `json:"load_assignment"` +} + +type loadAssignment struct { + Endpoints []endpoint `json:"endpoints"` +} + +type endpoint struct { + LBEndpoints []lbEndpoint `json:"lb_endpoints"` +} + +type lbEndpoint struct { + Endpoint ep `json:"endpoint"` + HealthStatus string `json:"health_status"` + LoadBalancingWeight float64 `json:"load_balancing_weight"` +} + +type ep struct { + Address address `json:"address"` +} + +type address struct { + SocketAddress socketAddress `json:"socket_address"` +} + +type socketAddress struct { + Address string `json:"address"` + PortValue float64 `json:"port_value"` +} + +type endpointsConfigDump struct { + ConfigType string `json:"@type"` + StaticEndpointConfigs []endpointConfigMap `json:"static_endpoint_configs"` + DynamicEndpointConfigs []endpointConfigMap `json:"dynamic_endpoint_configs"` +} + +type endpointConfigMap struct { + EndpointConfig endpointConfig `json:"endpoint_config"` +} + +type endpointConfig struct { + ConfigType string `json:"@type"` + Name string `json:"cluster_name"` + Endpoints []endpoint `json:"endpoints"` +} + +type listenersConfigDump struct { + ConfigType string `json:"@type"` + DynamicListeners []dynamicConfig `json:"dynamic_listeners"` + StaticListeners []listenerConfig `json:"static_listeners"` +} + +type dynamicConfig struct { + Name string `json:"name"` + ActiveState listenerConfig `json:"active_state"` +} + +type listenerConfig struct { + Listener listener `json:"listener"` + LastUpdated string `json:"last_updated"` +} + +type listener struct { + Name string `json:"name"` + Address address `json:"address"` + FilterChains []filterChain `json:"filter_chains"` + TrafficDirection string `json:"traffic_direction"` +} + +type filterChain struct { + Filters []filter `json:"filters"` + FilterChainMatch filterChainMatch `json:"filter_chain_match"` +} + +type filter struct { + Name string `json:"name"` + TypedConfig typedConfig `json:"typed_config"` +} + +type typedConfig struct { + Type string `json:"@type"` + Cluster string `json:"cluster"` + RouteConfig filterRouteConfig `json:"route_config"` + HttpFilters []httpFilter `json:"http_filters"` + Rules rules `json:"rules"` +} + +type filterRouteConfig struct { + Name string `json:"name"` + VirtualHosts []filterVirtualHost `json:"virtual_hosts"` +} + +type filterVirtualHost struct { + Name string `json:"name"` + Domains []string `json:"domains"` + Routes []filterRoute `json:"routes"` +} + +type filterRoute struct { + Match filterMatch `json:"match"` + Route filterRouteCluster `json:"route"` +} + +type filterMatch struct { + Prefix string `json:"prefix"` +} + +type filterRouteCluster struct { + Cluster string `json:"cluster"` +} + +type filterChainMatch struct { + PrefixRanges []prefixRange `json:"prefix_ranges"` +} + +type prefixRange struct { + AddressPrefix string `json:"address_prefix"` + PrefixLen float64 `json:"prefix_len"` +} + +type httpFilter struct { + TypedConfig httpTypedConfig `json:"typed_config"` +} + +type httpTypedConfig struct { + Rules rules `json:"rules"` +} + +type rules struct { + Action string `json:"action"` + Policies httpTypedConfigPolicies `json:"policies"` +} + +type httpTypedConfigPolicies struct { + ConsulIntentions httpTypedConfigConsulIntentions `json:"consul-intentions-layer4"` +} + +type httpTypedConfigConsulIntentions struct { + Principals []principal `json:"principals"` +} + +type principal struct { + Authenticated authenticated `json:"authenticated"` +} + +type authenticated struct { + PrincipalName principalName `json:"principal_name"` +} + +type principalName struct { + SafeRegex safeRegex `json:"safe_regex"` +} + +type safeRegex struct { + Regex string `json:"regex"` +} + +type routesConfigDump struct { + ConfigType string `json:"@type"` + StaticRouteConfigs []routeConfigMap `json:"static_route_configs"` +} + +type routeConfigMap struct { + RouteConfig routeConfig `json:"route_config"` + LastUpdated string `json:"last_updated"` +} + +type routeConfig struct { + Name string `json:"name"` + VirtualHosts []virtualHost `json:"virtual_hosts"` +} + +type virtualHost struct { + Routes []route `json:"routes"` +} + +type route struct { + Match routeMatch `json:"match"` + Route routeRoute `json:"route"` +} + +type routeMatch struct { + Prefix string `json:"prefix"` +} + +type routeRoute struct { + Cluster string `json:"cluster"` +} + +type secretsConfigDump struct { + ConfigType string `json:"@type"` + StaticSecrets []secretConfigMap `json:"static_secrets"` + DynamicActiveSecrets []secretConfigMap `json:"dynamic_active_secrets"` + DynamicWarmingSecrets []secretConfigMap `json:"dynamic_warming_secrets"` +} + +type secretConfigMap struct { + Name string `json:"name"` + Secret secret `json:"secret"` + LastUpdated string `json:"last_updated"` +} + +type secret struct { + Type string `json:"@type"` + TLSCertificate tlsCertificate `json:"tls_certificate"` + ValidationContext validationContext `json:"validation_context"` +} + +type tlsCertificate struct { + CertificateChain certificateChain `json:"certificate_chain"` +} + +type validationContext struct { + TrustedCA trustedCA `json:"trusted_ca"` +} + +type certificateChain struct { + InlineBytes string `json:"inline_bytes"` +} + +type trustedCA struct { + InlineBytes string `json:"inline_bytes"` +} + +type clusters struct { + ClusterStatuses []clusterStatus `json:"cluster_statuses"` +} + +type clusterStatus struct { + Name string `json:"name"` + HostStatuses []hostStatus `json:"host_statuses"` +} + +type hostStatus struct { + Address address `json:"address"` +} diff --git a/cli/cmd/proxy/read/filters.go b/cli/cmd/proxy/read/filters.go new file mode 100644 index 0000000000..c9d2d8f796 --- /dev/null +++ b/cli/cmd/proxy/read/filters.go @@ -0,0 +1,103 @@ +package read + +import ( + "strconv" + "strings" +) + +// FilterClusters takes a slice of clusters along with parameters for filtering +// those clusters. +// +// - `fqdn` filters clusters to only those with fully qualified domain names +// which contain the given value. +// - `address` filters clusters to only those with endpoint addresses which +// contain the given value. +// - `port` filters clusters to only those with endpoint addresses with ports +// that match the given value. If -1 is passed, no filtering will occur. +// +// The filters are applied in combination such that a cluster must adhere to +// all of the filtering values which are passed in. +func FilterClusters(clusters []Cluster, fqdn, address string, port int) []Cluster { + // No filtering no-op. + if fqdn == "" && address == "" && port == -1 { + return clusters + } + + portStr := ":" + strconv.Itoa(port) + + filtered := make([]Cluster, 0) + for _, cluster := range clusters { + if !strings.Contains(cluster.FullyQualifiedDomainName, fqdn) { + continue + } + + endpoints := strings.Join(cluster.Endpoints, " ") + if !strings.Contains(endpoints, address) || (port != -1 && !strings.Contains(endpoints, portStr)) { + continue + } + + hasFQDN := strings.Contains(cluster.FullyQualifiedDomainName, fqdn) + hasAddress := strings.Contains(endpoints, address) + hasPort := port == -1 || strings.Contains(endpoints, portStr) + + if hasFQDN && hasAddress && hasPort { + filtered = append(filtered, cluster) + } + } + + return filtered +} + +// FilterEndpoints takes a slice of endpoints along with parameters for filtering +// those endpoints: +// +// - `address` filters endpoints to only those with an address which contains +// the given value. +// - `port` filters endpoints to only those with an address which has a port +// that matches the given value. If -1 is passed, no filtering will occur. +// +// The filters are applied in combination such that an endpoint must adhere to +// all of the filtering values which are passed in. +func FilterEndpoints(endpoints []Endpoint, address string, port int) []Endpoint { + if address == "" && port == -1 { + return endpoints + } + + portStr := ":" + strconv.Itoa(port) + + filtered := make([]Endpoint, 0) + for _, endpoint := range endpoints { + if strings.Contains(endpoint.Address, address) && (port == -1 || strings.Contains(endpoint.Address, portStr)) { + filtered = append(filtered, endpoint) + } + } + + return filtered +} + +// FilterListeners takes a slice of listeners along with parameters for filtering +// those endpoints: +// +// - `address` filters listeners to only those with an address which contains +// the given value. +// - `port` filters listeners to only those with an address which has a port +// that matches the given value. If -1 is passed, no filtering will occur. +// +// The filters are applied in combination such that an listener must adhere to +// all of the filtering values which are passed in. +func FilterListeners(listeners []Listener, address string, port int) []Listener { + if address == "" && port == -1 { + return listeners + } + + portStr := ":" + strconv.Itoa(port) + + filtered := make([]Listener, 0) + for _, listener := range listeners { + if strings.Contains(listener.Address, address) && (port == -1 || strings.Contains(listener.Address, portStr)) { + filtered = append(filtered, listener) + } + } + + return filtered +} diff --git a/cli/cmd/proxy/read/filters_test.go b/cli/cmd/proxy/read/filters_test.go new file mode 100644 index 0000000000..48ff3a97da --- /dev/null +++ b/cli/cmd/proxy/read/filters_test.go @@ -0,0 +1,339 @@ +package read + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestFilterClusters(t *testing.T) { + given := []Cluster{ + { + FullyQualifiedDomainName: "local_agent", + Endpoints: []string{"192.168.79.187:8502"}, + }, + { + FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + { + FullyQualifiedDomainName: "local_admin", + Endpoints: []string{"127.0.0.1:5000"}, + }, + { + FullyQualifiedDomainName: "original-destination", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{"123.45.67.890:8080", "111.30.2.39:8080"}, + }, + } + + cases := map[string]struct { + fqdn string + address string + port int + expected []Cluster + }{ + "No filter": { + fqdn: "", + address: "", + port: -1, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_agent", + Endpoints: []string{"192.168.79.187:8502"}, + }, + { + FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + { + FullyQualifiedDomainName: "local_admin", + Endpoints: []string{"127.0.0.1:5000"}, + }, + { + FullyQualifiedDomainName: "original-destination", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{"123.45.67.890:8080", "111.30.2.39:8080"}, + }, + }, + }, + "Filter FQDN": { + fqdn: "default", + address: "", + port: -1, + expected: []Cluster{ + { + FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + }, + { + FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{"123.45.67.890:8080", "111.30.2.39:8080"}, + }, + }, + }, + "Filter address": { + fqdn: "", + address: "127.0.", + port: -1, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + { + FullyQualifiedDomainName: "local_admin", + Endpoints: []string{"127.0.0.1:5000"}, + }, + }, + }, + "Filter port": { + fqdn: "", + address: "", + port: 8080, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + { + FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{"123.45.67.890:8080", "111.30.2.39:8080"}, + }, + }, + }, + "Filter fqdn and address": { + fqdn: "local", + address: "127.0.0.1", + port: -1, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + { + FullyQualifiedDomainName: "local_admin", + Endpoints: []string{"127.0.0.1:5000"}, + }, + }, + }, + "Filter fqdn and port": { + fqdn: "local", + address: "", + port: 8080, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + }, + }, + "Filter address and port": { + fqdn: "", + address: "127.0.0.1", + port: 8080, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + }, + }, + }, + "Filter fqdn, address, and port": { + fqdn: "local", + address: "192.168.79.187", + port: 8502, + expected: []Cluster{ + { + FullyQualifiedDomainName: "local_agent", + Endpoints: []string{"192.168.79.187:8502"}, + }, + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + actual := FilterClusters(given, tc.fqdn, tc.address, tc.port) + require.Equal(t, tc.expected, actual) + }) + } +} + +func TestFilterEndpoints(t *testing.T) { + given := []Endpoint{ + { + Address: "192.168.79.187:8502", + }, + { + Address: "127.0.0.1:8080", + }, + { + Address: "192.168.31.201:20000", + }, + { + Address: "192.168.47.235:20000", + }, + { + Address: "192.168.71.254:20000", + }, + } + + cases := map[string]struct { + address string + port int + expected []Endpoint + }{ + "No filter": { + address: "", + port: -1, + expected: []Endpoint{ + { + Address: "192.168.79.187:8502", + }, + { + Address: "127.0.0.1:8080", + }, + { + Address: "192.168.31.201:20000", + }, + { + Address: "192.168.47.235:20000", + }, + { + Address: "192.168.71.254:20000", + }, + }, + }, + "Filter address": { + address: "127.0.0.1", + port: -1, + expected: []Endpoint{ + { + Address: "127.0.0.1:8080", + }, + }, + }, + "Filter port": { + address: "", + port: 20000, + expected: []Endpoint{ + { + Address: "192.168.31.201:20000", + }, + { + Address: "192.168.47.235:20000", + }, + { + Address: "192.168.71.254:20000", + }, + }, + }, + "Filter address and port": { + address: "235", + port: 20000, + expected: []Endpoint{ + { + Address: "192.168.47.235:20000", + }, + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + actual := FilterEndpoints(given, tc.address, tc.port) + require.Equal(t, tc.expected, actual) + }) + } +} + +func TestFilterListeners(t *testing.T) { + given := []Listener{ + { + Address: "192.168.69.179:20000", + }, + { + Address: "127.0.0.1:15001", + }, + } + + cases := map[string]struct { + address string + port int + expected []Listener + }{ + "No filter": { + address: "", + port: -1, + expected: []Listener{ + { + Address: "192.168.69.179:20000", + }, + { + Address: "127.0.0.1:15001", + }, + }, + }, + "Filter address": { + address: "127.0.0.1", + port: -1, + expected: []Listener{ + { + Address: "127.0.0.1:15001", + }, + }, + }, + "Filter port": { + address: "", + port: 20000, + expected: []Listener{ + { + Address: "192.168.69.179:20000", + }, + }, + }, + "Filter address and port": { + address: "192.168.69.179", + port: 20000, + expected: []Listener{ + { + Address: "192.168.69.179:20000", + }, + }, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + actual := FilterListeners(given, tc.address, tc.port) + require.Equal(t, tc.expected, actual) + }) + } +} diff --git a/cli/cmd/proxy/read/format.go b/cli/cmd/proxy/read/format.go new file mode 100644 index 0000000000..97d5ada86a --- /dev/null +++ b/cli/cmd/proxy/read/format.go @@ -0,0 +1,76 @@ +package read + +import ( + "fmt" + "strings" + + "github.com/hashicorp/consul-k8s/cli/common/terminal" +) + +func formatClusters(clusters []Cluster) *terminal.Table { + table := terminal.NewTable("Name", "FQDN", "Endpoints", "Type", "Last Updated") + for _, cluster := range clusters { + table.AddRow([]string{cluster.Name, cluster.FullyQualifiedDomainName, strings.Join(cluster.Endpoints, ", "), + cluster.Type, cluster.LastUpdated}, []string{}) + } + + return table +} + +func formatEndpoints(endpoints []Endpoint) *terminal.Table { + table := terminal.NewTable("Address:Port", "Cluster", "Weight", "Status") + for _, endpoint := range endpoints { + var statusColor string + if endpoint.Status == "HEALTHY" { + statusColor = "green" + } else { + statusColor = "red" + } + + table.AddRow( + []string{endpoint.Address, endpoint.Cluster, fmt.Sprintf("%.2f", endpoint.Weight), endpoint.Status}, + []string{"", "", "", statusColor}) + } + + return table +} + +func formatListeners(listeners []Listener) *terminal.Table { + table := terminal.NewTable("Name", "Address:Port", "Direction", "Filter Chain Match", "Filters", "Last Updated") + for _, listener := range listeners { + for index, filter := range listener.FilterChain { + // Print each element of the filter chain in a separate line + // without repeating the name, address, etc. + filters := strings.Join(filter.Filters, "\n") + if index == 0 { + table.AddRow( + []string{listener.Name, listener.Address, listener.Direction, filter.FilterChainMatch, filters, listener.LastUpdated}, + []string{}) + } else { + table.AddRow( + []string{"", "", "", filter.FilterChainMatch, filters}, + []string{}) + } + } + } + + return table +} + +func formatRoutes(routes []Route) *terminal.Table { + table := terminal.NewTable("Name", "Destination Cluster", "Last Updated") + for _, route := range routes { + table.AddRow([]string{route.Name, route.DestinationCluster, route.LastUpdated}, []string{}) + } + + return table +} + +func formatSecrets(secrets []Secret) *terminal.Table { + table := terminal.NewTable("Name", "Type", "Last Updated") + for _, secret := range secrets { + table.AddRow([]string{secret.Name, secret.Type, secret.LastUpdated}, []string{}) + } + + return table +} diff --git a/cli/cmd/proxy/read/format_test.go b/cli/cmd/proxy/read/format_test.go new file mode 100644 index 0000000000..7d6f975d39 --- /dev/null +++ b/cli/cmd/proxy/read/format_test.go @@ -0,0 +1,312 @@ +package read + +import ( + "bytes" + "context" + "testing" + + "github.com/hashicorp/consul-k8s/cli/common/terminal" + "github.com/stretchr/testify/require" +) + +func TestFormatClusters(t *testing.T) { + // These regular expressions must be present in the output. + expected := []string{ + "Name.*FQDN.*Endpoints.*Type.*Last Updated", + "local_agent.*local_agent.*192\\.168\\.79\\.187:8502.*STATIC.*2022-05-13T04:22:39\\.553Z", + "local_app.*local_app.*127\\.0\\.0\\.1:8080.*STATIC.*2022-05-13T04:22:39\\.655Z", + "client.*client\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS.*2022-06-09T00:39:12\\.948Z", + "frontend.*frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS.*2022-06-09T00:39:12\\.855Z", + "original-destination.*original-destination.*ORIGINAL_DST.*2022-05-13T04:22:39.743Z", + "server.*server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul.*EDS.*2022-06-09T00:39:12\\.754Z", + } + + given := []Cluster{ + { + Name: "local_agent", + FullyQualifiedDomainName: "local_agent", + Endpoints: []string{"192.168.79.187:8502"}, + Type: "STATIC", + LastUpdated: "2022-05-13T04:22:39.553Z", + }, + { + Name: "client", + FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + Type: "EDS", + LastUpdated: "2022-06-09T00:39:12.948Z", + }, + { + Name: "frontend", + FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + Type: "EDS", + LastUpdated: "2022-06-09T00:39:12.855Z", + }, + { + Name: "local_app", + FullyQualifiedDomainName: "local_app", + Endpoints: []string{"127.0.0.1:8080"}, + Type: "STATIC", + LastUpdated: "2022-05-13T04:22:39.655Z", + }, + { + Name: "original-destination", + FullyQualifiedDomainName: "original-destination", + Endpoints: []string{}, + Type: "ORIGINAL_DST", + LastUpdated: "2022-05-13T04:22:39.743Z", + }, + { + Name: "server", + FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + Endpoints: []string{}, + Type: "EDS", + LastUpdated: "2022-06-09T00:39:12.754Z", + }, + } + + expectedHeaders := []string{"Name", "FQDN", "Endpoints", "Type", "Last Updated"} + + table := formatClusters(given) + + require.Equal(t, expectedHeaders, table.Headers) + require.Equal(t, len(given), len(table.Rows)) + + buf := new(bytes.Buffer) + terminal.NewUI(context.Background(), buf).Table(table) + + actual := buf.String() + for _, expression := range expected { + require.Regexp(t, expression, actual) + } +} + +func TestFormatEndpoints(t *testing.T) { + // These regular expressions must be present in the output. + expected := []string{ + "Address:Port.*Cluster.*Weight.*Status", + "192.168.79.187:8502.*local_agent.*1.00.*HEALTHY", + "127.0.0.1:8080.*local_app.*1.00.*HEALTHY", + "192.168.31.201:20000.*1.00.*HEALTHY", + "192.168.47.235:20000.*1.00.*HEALTHY", + "192.168.71.254:20000.*1.00.*HEALTHY", + "192.168.63.120:20000.*1.00.*HEALTHY", + "192.168.18.110:20000.*1.00.*HEALTHY", + "192.168.52.101:20000.*1.00.*HEALTHY", + "192.168.65.131:20000.*1.00.*HEALTHY", + } + + given := []Endpoint{ + { + Address: "192.168.79.187:8502", + Cluster: "local_agent", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "127.0.0.1:8080", + Cluster: "local_app", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.31.201:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.47.235:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.71.254:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.63.120:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.18.110:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.52.101:20000", + Weight: 1, + Status: "HEALTHY", + }, + { + Address: "192.168.65.131:20000", + Weight: 1, + Status: "HEALTHY", + }, + } + + expectedHeaders := []string{"Address:Port", "Cluster", "Weight", "Status"} + + table := formatEndpoints(given) + + require.Equal(t, expectedHeaders, table.Headers) + require.Equal(t, len(given), len(table.Rows)) + + buf := new(bytes.Buffer) + terminal.NewUI(context.Background(), buf).Table(table) + + actual := buf.String() + for _, expression := range expected { + require.Regexp(t, expression, actual) + } +} + +func TestFormatListeners(t *testing.T) { + // These regular expressions must be present in the output. + expected := []string{ + "Name.*Address:Port.*Direction.*Filter Chain Match.*Filters.*Last Updated", + "public_listener.*192\\.168\\.69\\.179:20000.*INBOUND.*Any.*\\* -> local_app/.*2022-06-09T00:39:27\\.668Z", + "outbound_listener.*127.0.0.1:15001.*OUTBOUND.*10\\.100\\.134\\.173/32, 240\\.0\\.0\\.3/32.*-> client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul.*2022-05-24T17:41:59\\.079Z", + "10\\.100\\.254\\.176/32, 240\\.0\\.0\\.4/32.*\\* -> server\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul/", + "10\\.100\\.31\\.2/32, 240\\.0\\.0\\.2/32.*-> frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul", + "Any.*-> original-destination", + } + + given := []Listener{ + { + Name: "public_listener", + Address: "192.168.69.179:20000", + FilterChain: []FilterChain{ + { + FilterChainMatch: "Any", + Filters: []string{"* -> local_app/"}, + }, + }, + Direction: "INBOUND", + LastUpdated: "2022-06-09T00:39:27.668Z", + }, + { + Name: "outbound_listener", + Address: "127.0.0.1:15001", + FilterChain: []FilterChain{ + { + FilterChainMatch: "10.100.134.173/32, 240.0.0.3/32", + Filters: []string{"-> client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, + }, + { + FilterChainMatch: "10.100.254.176/32, 240.0.0.4/32", + Filters: []string{"* -> server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/"}, + }, + { + FilterChainMatch: "10.100.31.2/32, 240.0.0.2/32", + Filters: []string{ + "-> frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + }, + }, + { + FilterChainMatch: "Any", + Filters: []string{"-> original-destination"}, + }, + }, + Direction: "OUTBOUND", + LastUpdated: "2022-05-24T17:41:59.079Z", + }, + } + + expectedHeaders := []string{"Name", "Address:Port", "Direction", "Filter Chain Match", "Filters", "Last Updated"} + + // Listeners tables split filter chain information across rows. + expectedRowCount := 0 + for _, element := range given { + expectedRowCount += len(element.FilterChain) + } + + table := formatListeners(given) + + require.Equal(t, expectedHeaders, table.Headers) + require.Equal(t, expectedRowCount, len(table.Rows)) + + buf := new(bytes.Buffer) + terminal.NewUI(context.Background(), buf).Table(table) + + actual := buf.String() + for _, expression := range expected { + require.Regexp(t, expression, actual) + } +} + +func TestFormatRoutes(t *testing.T) { + // These regular expressions must be present in the output. + expected := []string{ + "Name.*Destination Cluster.*Last Updated", + "public_listener.*local_app/.*2022-06-09T00:39:27.667Z", + "server.*server\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul/.*2022-05-24T17:41:59\\.078Z", + } + + given := []Route{ + { + Name: "public_listener", + DestinationCluster: "local_app/", + LastUpdated: "2022-06-09T00:39:27.667Z", + }, + { + Name: "server", + DestinationCluster: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/", + LastUpdated: "2022-05-24T17:41:59.078Z", + }, + } + + expectedHeaders := []string{"Name", "Destination Cluster", "Last Updated"} + + table := formatRoutes(given) + + require.Equal(t, expectedHeaders, table.Headers) + require.Equal(t, len(given), len(table.Rows)) + + buf := new(bytes.Buffer) + terminal.NewUI(context.Background(), buf).Table(table) + + actual := buf.String() + for _, expression := range expected { + require.Regexp(t, expression, actual) + } +} + +func TestFormatSecrets(t *testing.T) { + // These regular expressions must be present in the output. + expected := []string{ + "Name.*Type.*Last Updated", + "default.*Dynamic Active.*2022-05-24T17:41:59.078Z", + "ROOTCA.*Dynamic Warming.*2022-03-15T05:14:22.868Z", + } + + given := []Secret{ + { + Name: "default", + Type: "Dynamic Active", + LastUpdated: "2022-05-24T17:41:59.078Z", + }, + { + Name: "ROOTCA", + Type: "Dynamic Warming", + LastUpdated: "2022-03-15T05:14:22.868Z", + }, + } + + expectedHeaders := []string{"Name", "Type", "Last Updated"} + + table := formatSecrets(given) + + require.Equal(t, expectedHeaders, table.Headers) + require.Equal(t, len(given), len(table.Rows)) + + buf := new(bytes.Buffer) + terminal.NewUI(context.Background(), buf).Table(table) + + actual := buf.String() + for _, expression := range expected { + require.Regexp(t, expression, actual) + } +} diff --git a/cli/cmd/proxy/read/test_clusters.json b/cli/cmd/proxy/read/test_clusters.json new file mode 100644 index 0000000000..55a4c244b2 --- /dev/null +++ b/cli/cmd/proxy/read/test_clusters.json @@ -0,0 +1,302 @@ +{ + "cluster_statuses": [ + { + "name": "local_app", + "added_via_api": true, + "host_statuses": [ + { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 0 + } + }, + "stats": [ + { + "value": "6", + "name": "cx_connect_fail" + }, + { + "value": "38", + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": { + + } + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "local_app" + }, + { + "name": "self_admin", + "host_statuses": [ + { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 19000 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "value": "1", + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "value": "26", + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "value": "26", + "name": "rq_total" + }, + { + "type": "GAUGE", + "value": "1", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": { + + } + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "self_admin" + }, + { + "name": "original-destination", + "added_via_api": true, + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "original-destination" + }, + { + "name": "static-server.default.dc1.internal.80d0b664-149b-52fa-c6ae-3dad962bdaa8.consul", + "added_via_api": true, + "host_statuses": [ + { + "address": { + "socket_address": { + "address": "10.244.0.74", + "port_value": 20000 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": { + + } + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "static-server.default.dc1.internal.80d0b664-149b-52fa-c6ae-3dad962bdaa8.consul" + }, + { + "name": "local_agent", + "host_statuses": [ + { + "address": { + "socket_address": { + "address": "172.18.0.2", + "port_value": 8502 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "value": "1", + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "value": "1", + "name": "rq_total" + }, + { + "type": "GAUGE", + "value": "1", + "name": "cx_active" + }, + { + "type": "GAUGE", + "value": "1", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": { + + } + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "local_agent" + } + ] +} diff --git a/cli/cmd/proxy/read/test_config_dump.json b/cli/cmd/proxy/read/test_config_dump.json new file mode 100644 index 0000000000..982f50483d --- /dev/null +++ b/cli/cmd/proxy/read/test_config_dump.json @@ -0,0 +1,2019 @@ +{ + "configs": [ + { + "@type": "type.googleapis.com/envoy.admin.v3.BootstrapConfigDump", + "bootstrap": { + "node": { + "id": "backend-658b679b45-d5xlb-backend-sidecar-proxy", + "cluster": "backend", + "metadata": { + "partition": "default", + "namespace": "default" + }, + "user_agent_name": "envoy", + "user_agent_build_version": { + "version": { + "major_number": 1, + "minor_number": 22 + }, + "metadata": { + "revision.status": "Clean", + "ssl.version": "BoringSSL", + "revision.sha": "dcd329a2e95b54f754b17aceca3f72724294b502", + "build.type": "RELEASE" + } + }, + "extensions": [ + { + "name": "envoy.filters.thrift.header_to_metadata", + "category": "envoy.thrift_proxy.filters" + }, + { + "name": "envoy.filters.thrift.rate_limit", + "category": "envoy.thrift_proxy.filters" + }, + { + "name": "envoy.filters.thrift.router", + "category": "envoy.thrift_proxy.filters" + }, + { + "name": "envoy.request_id.uuid", + "category": "envoy.request_id" + }, + { + "name": "dubbo", + "category": "envoy.dubbo_proxy.protocols" + }, + { + "name": "envoy.filters.connection_pools.tcp.generic", + "category": "envoy.upstreams" + }, + { + "name": "envoy.client_ssl_auth", + "category": "envoy.filters.network" + }, + { + "name": "envoy.echo", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.client_ssl_auth", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.connection_limit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.direct_response", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.dubbo_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.echo", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.ext_authz", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.http_connection_manager", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.local_ratelimit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.mongo_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.ratelimit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.rbac", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.redis_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.sni_cluster", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.sni_dynamic_forward_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.tcp_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.thrift_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.wasm", + "category": "envoy.filters.network" + }, + { + "name": "envoy.filters.network.zookeeper_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.http_connection_manager", + "category": "envoy.filters.network" + }, + { + "name": "envoy.mongo_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.ratelimit", + "category": "envoy.filters.network" + }, + { + "name": "envoy.redis_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.tcp_proxy", + "category": "envoy.filters.network" + }, + { + "name": "envoy.dynamic.ot", + "category": "envoy.tracers" + }, + { + "name": "envoy.lightstep", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.datadog", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.dynamic_ot", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.lightstep", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.opencensus", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.skywalking", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.xray", + "category": "envoy.tracers" + }, + { + "name": "envoy.tracers.zipkin", + "category": "envoy.tracers" + }, + { + "name": "envoy.zipkin", + "category": "envoy.tracers" + }, + { + "name": "envoy.cluster.eds", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.logical_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.original_dst", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.static", + "category": "envoy.clusters" + }, + { + "name": "envoy.cluster.strict_dns", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.aggregate", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.dynamic_forward_proxy", + "category": "envoy.clusters" + }, + { + "name": "envoy.clusters.redis", + "category": "envoy.clusters" + }, + { + "name": "envoy.tls.cert_validator.default", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.tls.cert_validator.spiffe", + "category": "envoy.tls.cert_validator" + }, + { + "name": "envoy.http.original_ip_detection.custom_header", + "category": "envoy.http.original_ip_detection" + }, + { + "name": "envoy.http.original_ip_detection.xff", + "category": "envoy.http.original_ip_detection" + }, + { + "name": "envoy.retry_priorities.previous_priorities", + "category": "envoy.retry_priorities" + }, + { + "name": "envoy.filters.dubbo.router", + "category": "envoy.dubbo_proxy.filters" + }, + { + "name": "envoy.filters.listener.http_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.filters.listener.original_dst", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.filters.listener.original_src", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.filters.listener.proxy_protocol", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.filters.listener.tls_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.http_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_dst", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.original_src", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.proxy_protocol", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.listener.tls_inspector", + "category": "envoy.filters.listener" + }, + { + "name": "envoy.compression.brotli.decompressor", + "category": "envoy.compression.decompressor" + }, + { + "name": "envoy.compression.gzip.decompressor", + "category": "envoy.compression.decompressor" + }, + { + "name": "envoy.compression.zstd.decompressor", + "category": "envoy.compression.decompressor" + }, + { + "name": "envoy.internal_redirect_predicates.allow_listed_routes", + "category": "envoy.internal_redirect_predicates" + }, + { + "name": "envoy.internal_redirect_predicates.previous_routes", + "category": "envoy.internal_redirect_predicates" + }, + { + "name": "envoy.internal_redirect_predicates.safe_cross_scheme", + "category": "envoy.internal_redirect_predicates" + }, + { + "name": "envoy.dog_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.graphite_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.metrics_service", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.dog_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.graphite_statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.hystrix", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.metrics_service", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.stat_sinks.wasm", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.statsd", + "category": "envoy.stats_sinks" + }, + { + "name": "envoy.access_loggers.file", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.access_loggers.http_grpc", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.access_loggers.open_telemetry", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.access_loggers.stderr", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.access_loggers.stdout", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.access_loggers.tcp_grpc", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.access_loggers.wasm", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.file_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.http_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.open_telemetry_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stderr_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.stdout_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.tcp_grpc_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.wasm_access_log", + "category": "envoy.access_loggers" + }, + { + "name": "envoy.filters.udp.dns_filter", + "category": "envoy.filters.udp_listener" + }, + { + "name": "envoy.filters.udp_listener.udp_proxy", + "category": "envoy.filters.udp_listener" + }, + { + "name": "envoy.access_loggers.extension_filters.cel", + "category": "envoy.access_logger.extension_filters" + }, + { + "name": "envoy.key_value.file_based", + "category": "envoy.common.key_value" + }, + { + "name": "envoy.rbac.matchers.upstream_ip_port", + "category": "envoy.rbac.matchers" + }, + { + "name": "composite-action", + "category": "envoy.matching.action" + }, + { + "name": "skip", + "category": "envoy.matching.action" + }, + { + "name": "envoy.matching.common_inputs.environment_variable", + "category": "envoy.matching.common_inputs" + }, + { + "name": "envoy.resource_monitors.fixed_heap", + "category": "envoy.resource_monitors" + }, + { + "name": "envoy.resource_monitors.injected_resource", + "category": "envoy.resource_monitors" + }, + { + "name": "envoy.watchdog.abort_action", + "category": "envoy.guarddog_actions" + }, + { + "name": "envoy.watchdog.profile_action", + "category": "envoy.guarddog_actions" + }, + { + "name": "default", + "category": "network.connection.client" + }, + { + "name": "envoy_internal", + "category": "network.connection.client" + }, + { + "name": "envoy.matching.custom_matchers.trie_matcher", + "category": "envoy.matching.network.custom_matchers" + }, + { + "name": "envoy.bandwidth_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.buffer", + "category": "envoy.filters.http" + }, + { + "name": "envoy.cors", + "category": "envoy.filters.http" + }, + { + "name": "envoy.csrf", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_authz", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ext_proc", + "category": "envoy.filters.http" + }, + { + "name": "envoy.fault", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.adaptive_concurrency", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.admission_control", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.alternate_protocols_cache", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.aws_lambda", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.aws_request_signing", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.bandwidth_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.buffer", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.cache", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.cdn_loop", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.composite", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.compressor", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.cors", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.csrf", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.decompressor", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.dynamic_forward_proxy", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.dynamo", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.ext_authz", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.ext_proc", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.fault", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.gcp_authn", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.grpc_http1_bridge", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.grpc_http1_reverse_bridge", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.grpc_json_transcoder", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.grpc_stats", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.grpc_web", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.header_to_metadata", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.health_check", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.ip_tagging", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.jwt_authn", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.local_ratelimit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.lua", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.oauth2", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.on_demand", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.original_src", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.ratelimit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.rbac", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.router", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.set_metadata", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.stateful_session", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.tap", + "category": "envoy.filters.http" + }, + { + "name": "envoy.filters.http.wasm", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_http1_bridge", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_json_transcoder", + "category": "envoy.filters.http" + }, + { + "name": "envoy.grpc_web", + "category": "envoy.filters.http" + }, + { + "name": "envoy.health_check", + "category": "envoy.filters.http" + }, + { + "name": "envoy.http_dynamo_filter", + "category": "envoy.filters.http" + }, + { + "name": "envoy.ip_tagging", + "category": "envoy.filters.http" + }, + { + "name": "envoy.local_rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.lua", + "category": "envoy.filters.http" + }, + { + "name": "envoy.rate_limit", + "category": "envoy.filters.http" + }, + { + "name": "envoy.router", + "category": "envoy.filters.http" + }, + { + "name": "match-wrapper", + "category": "envoy.filters.http" + }, + { + "name": "envoy.quic.crypto_stream.server.quiche", + "category": "envoy.quic.server.crypto_stream" + }, + { + "name": "dubbo.hessian2", + "category": "envoy.dubbo_proxy.serializers" + }, + { + "name": "envoy.wasm.runtime.null", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.wasm.runtime.v8", + "category": "envoy.wasm.runtime" + }, + { + "name": "envoy.matching.inputs.application_protocol", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.destination_ip", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.destination_port", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.direct_source_ip", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.server_name", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.source_ip", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.source_port", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.source_type", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.inputs.transport_protocol", + "category": "envoy.matching.network.input" + }, + { + "name": "envoy.matching.matchers.consistent_hashing", + "category": "envoy.matching.input_matchers" + }, + { + "name": "envoy.matching.matchers.ip", + "category": "envoy.matching.input_matchers" + }, + { + "name": "preserve_case", + "category": "envoy.http.stateful_header_formatters" + }, + { + "name": "envoy.config.validators.minimum_clusters", + "category": "envoy.config.validators" + }, + { + "name": "envoy.config.validators.minimum_clusters_validator", + "category": "envoy.config.validators" + }, + { + "name": "envoy.bootstrap.internal_listener", + "category": "envoy.bootstrap" + }, + { + "name": "envoy.bootstrap.wasm", + "category": "envoy.bootstrap" + }, + { + "name": "envoy.extensions.network.socket_interface.default_socket_interface", + "category": "envoy.bootstrap" + }, + { + "name": "envoy.grpc_credentials.aws_iam", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.default", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.grpc_credentials.file_based_metadata", + "category": "envoy.grpc_credentials" + }, + { + "name": "envoy.rate_limit_descriptors.expr", + "category": "envoy.rate_limit_descriptors" + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "framed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "header", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "unframed", + "category": "envoy.thrift_proxy.transports" + }, + { + "name": "envoy.compression.brotli.compressor", + "category": "envoy.compression.compressor" + }, + { + "name": "envoy.compression.gzip.compressor", + "category": "envoy.compression.compressor" + }, + { + "name": "envoy.compression.zstd.compressor", + "category": "envoy.compression.compressor" + }, + { + "name": "envoy.network.dns_resolver.cares", + "category": "envoy.network.dns_resolver" + }, + { + "name": "envoy.health_checkers.redis", + "category": "envoy.health_checkers" + }, + { + "name": "envoy.ip", + "category": "envoy.resolvers" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.downstream" + }, + { + "name": "envoy.formatter.metadata", + "category": "envoy.formatter" + }, + { + "name": "envoy.formatter.req_without_query", + "category": "envoy.formatter" + }, + { + "name": "auto", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "binary/non-strict", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "compact", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "twitter", + "category": "envoy.thrift_proxy.protocols" + }, + { + "name": "envoy.extensions.http.cache.simple", + "category": "envoy.http.cache" + }, + { + "name": "envoy.quic.proof_source.filter_chain", + "category": "envoy.quic.proof_source" + }, + { + "name": "default", + "category": "envoy.dubbo_proxy.route_matchers" + }, + { + "name": "envoy.transport_sockets.alts", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.quic", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.raw_buffer", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.starttls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.tap", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.tcp_stats", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.tls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.transport_sockets.upstream_proxy_protocol", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "raw_buffer", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "starttls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "tls", + "category": "envoy.transport_sockets.upstream" + }, + { + "name": "envoy.http.stateful_session.cookie", + "category": "envoy.http.stateful_session" + }, + { + "name": "envoy.retry_host_predicates.omit_canary_hosts", + "category": "envoy.retry_host_predicates" + }, + { + "name": "envoy.retry_host_predicates.omit_host_metadata", + "category": "envoy.retry_host_predicates" + }, + { + "name": "envoy.retry_host_predicates.previous_hosts", + "category": "envoy.retry_host_predicates" + }, + { + "name": "envoy.extensions.upstreams.http.v3.HttpProtocolOptions", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.upstreams.http.http_protocol_options", + "category": "envoy.upstream_options" + }, + { + "name": "envoy.matching.inputs.request_headers", + "category": "envoy.matching.http.input" + }, + { + "name": "envoy.matching.inputs.request_trailers", + "category": "envoy.matching.http.input" + }, + { + "name": "envoy.matching.inputs.response_headers", + "category": "envoy.matching.http.input" + }, + { + "name": "envoy.matching.inputs.response_trailers", + "category": "envoy.matching.http.input" + } + ] + }, + "static_resources": { + "clusters": [ + { + "name": "local_agent", + "type": "STATIC", + "connect_timeout": "1s", + "http2_protocol_options": {}, + "transport_socket": { + "name": "tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "validation_context": { + "trusted_ca": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIDQTCCAuigAwIBAgIUH1N2/59JC/WVKUx81/tPZhzvkbowCgYIKoZIzj0EAwIw\ngZExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5j\naXNjbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1\nMRcwFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjEYMBYGA1UEAxMPQ29uc3VsIEFnZW50\nIENBMB4XDTIyMDUxMzA0MTYyMVoXDTMyMDUxMDA0MTcyMVowgZExCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEaMBgGA1UE\nCRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcwFQYDVQQKEw5I\nYXNoaUNvcnAgSW5jLjEYMBYGA1UEAxMPQ29uc3VsIEFnZW50IENBMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEKGiRtWa7AnHvX3/MRVsNUiAJljkkGSKd/sH2ayyF\nJjIibn/UkNE7vGrVcuPsh5/gZ5ATb6TQPU5EKARir51++aOCARowggEWMA4GA1Ud\nDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0T\nAQH/BAUwAwEB/zBoBgNVHQ4EYQRfNDY6MTQ6NTg6MWM6Y2E6N2Q6NTM6ZTM6MmM6\nNTM6NGI6NjE6NjA6MDA6NTM6MmQ6OTY6YWQ6MjI6OWE6YmY6MzE6YzE6OTg6MmM6\nMWU6YTY6YTI6MTk6ZjE6NmM6ZGQwagYDVR0jBGMwYYBfNDY6MTQ6NTg6MWM6Y2E6\nN2Q6NTM6ZTM6MmM6NTM6NGI6NjE6NjA6MDA6NTM6MmQ6OTY6YWQ6MjI6OWE6YmY6\nMzE6YzE6OTg6MmM6MWU6YTY6YTI6MTk6ZjE6NmM6ZGQwCgYIKoZIzj0EAwIDRwAw\nRAIgBr/joI/OhA3QgTbxCnz7k+YrNpuVz6dKGSqbUUZ0dW0CIGA5sUyhlCnd1NCg\nSUim9u7YFd9tZiew747LovPQmMAg\n-----END CERTIFICATE-----\n\n" + } + } + } + } + }, + "load_assignment": { + "cluster_name": "local_agent", + "endpoints": [ + { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.79.187", + "port_value": 8502 + } + } + } + } + ] + } + ] + } + } + ] + }, + "dynamic_resources": { + "lds_config": { + "ads": {}, + "resource_api_version": "V3" + }, + "cds_config": { + "ads": {}, + "resource_api_version": "V3" + }, + "ads_config": { + "api_type": "DELTA_GRPC", + "grpc_services": [ + { + "envoy_grpc": { + "cluster_name": "local_agent" + }, + "initial_metadata": [ + { + "key": "x-consul-token" + } + ] + } + ], + "transport_api_version": "V3" + } + }, + "admin": { + "access_log_path": "/dev/null", + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 19000 + } + } + }, + "stats_config": { + "stats_tags": [ + { + "tag_name": "consul.destination.custom_hash", + "regex": "^cluster\\.(?:passthrough~)?((?:([^.]+)~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.service_subset", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.service", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.namespace", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.partition", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.datacenter", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.routing_type", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.trust_domain", + "regex": "^cluster\\.(?:passthrough~)?((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.([^.]+)\\.consul\\.)" + }, + { + "tag_name": "consul.destination.target", + "regex": "^cluster\\.(?:passthrough~)?(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.destination.full_target", + "regex": "^cluster\\.(?:passthrough~)?(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+)\\.consul\\.)" + }, + { + "tag_name": "consul.upstream.service", + "regex": "^(?:tcp|http)\\.upstream\\.(([^.]+)(?:\\.[^.]+)?(?:\\.[^.]+)?\\.[^.]+\\.)" + }, + { + "tag_name": "consul.upstream.datacenter", + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.[^.]+)?(?:\\.[^.]+)?\\.([^.]+)\\.)" + }, + { + "tag_name": "consul.upstream.namespace", + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.([^.]+))?(?:\\.[^.]+)?\\.[^.]+\\.)" + }, + { + "tag_name": "consul.upstream.partition", + "regex": "^(?:tcp|http)\\.upstream\\.([^.]+(?:\\.[^.]+)?(?:\\.([^.]+))?\\.[^.]+\\.)" + }, + { + "tag_name": "consul.custom_hash", + "regex": "^cluster\\.((?:([^.]+)~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.service_subset", + "regex": "^cluster\\.((?:[^.]+~)?(?:([^.]+)\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.service", + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.namespace", + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.datacenter", + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?([^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.routing_type", + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.([^.]+)\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.trust_domain", + "regex": "^cluster\\.((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.([^.]+)\\.consul\\.)" + }, + { + "tag_name": "consul.target", + "regex": "^cluster\\.(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+)\\.[^.]+\\.[^.]+\\.consul\\.)" + }, + { + "tag_name": "consul.full_target", + "regex": "^cluster\\.(((?:[^.]+~)?(?:[^.]+\\.)?[^.]+\\.[^.]+\\.(?:[^.]+\\.)?[^.]+\\.[^.]+\\.[^.]+)\\.consul\\.)" + }, + { + "tag_name": "local_cluster", + "fixed_value": "backend" + }, + { + "tag_name": "consul.source.service", + "fixed_value": "backend" + }, + { + "tag_name": "consul.source.namespace", + "fixed_value": "default" + }, + { + "tag_name": "consul.source.partition", + "fixed_value": "default" + }, + { + "tag_name": "consul.source.datacenter", + "fixed_value": "dc1" + } + ], + "use_all_default_tags": true + } + }, + "last_updated": "2022-05-13T04:22:39.488Z" + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ClustersConfigDump", + "static_clusters": [ + { + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_agent", + "type": "STATIC", + "connect_timeout": "1s", + "http2_protocol_options": {}, + "transport_socket": { + "name": "tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "validation_context": { + "trusted_ca": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIIDQTCCAuigAwIBAgIUH1N2/59JC/WVKUx81/tPZhzvkbowCgYIKoZIzj0EAwIw\ngZExCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5j\naXNjbzEaMBgGA1UECRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1\nMRcwFQYDVQQKEw5IYXNoaUNvcnAgSW5jLjEYMBYGA1UEAxMPQ29uc3VsIEFnZW50\nIENBMB4XDTIyMDUxMzA0MTYyMVoXDTMyMDUxMDA0MTcyMVowgZExCzAJBgNVBAYT\nAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNU2FuIEZyYW5jaXNjbzEaMBgGA1UE\nCRMRMTAxIFNlY29uZCBTdHJlZXQxDjAMBgNVBBETBTk0MTA1MRcwFQYDVQQKEw5I\nYXNoaUNvcnAgSW5jLjEYMBYGA1UEAxMPQ29uc3VsIEFnZW50IENBMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEKGiRtWa7AnHvX3/MRVsNUiAJljkkGSKd/sH2ayyF\nJjIibn/UkNE7vGrVcuPsh5/gZ5ATb6TQPU5EKARir51++aOCARowggEWMA4GA1Ud\nDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0T\nAQH/BAUwAwEB/zBoBgNVHQ4EYQRfNDY6MTQ6NTg6MWM6Y2E6N2Q6NTM6ZTM6MmM6\nNTM6NGI6NjE6NjA6MDA6NTM6MmQ6OTY6YWQ6MjI6OWE6YmY6MzE6YzE6OTg6MmM6\nMWU6YTY6YTI6MTk6ZjE6NmM6ZGQwagYDVR0jBGMwYYBfNDY6MTQ6NTg6MWM6Y2E6\nN2Q6NTM6ZTM6MmM6NTM6NGI6NjE6NjA6MDA6NTM6MmQ6OTY6YWQ6MjI6OWE6YmY6\nMzE6YzE6OTg6MmM6MWU6YTY6YTI6MTk6ZjE6NmM6ZGQwCgYIKoZIzj0EAwIDRwAw\nRAIgBr/joI/OhA3QgTbxCnz7k+YrNpuVz6dKGSqbUUZ0dW0CIGA5sUyhlCnd1NCg\nSUim9u7YFd9tZiew747LovPQmMAg\n-----END CERTIFICATE-----\n\n" + } + } + } + } + }, + "load_assignment": { + "cluster_name": "local_agent", + "endpoints": [ + { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.79.187", + "port_value": 8502 + } + } + } + } + ] + } + ] + } + }, + "last_updated": "2022-05-13T04:22:39.553Z" + } + ], + "dynamic_active_clusters": [ + { + "version_info": "877646fa9c433fbe25febc99b0725a44ab606d9f5407b76a6b7513edd1ac8af2", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + "type": "EDS", + "eds_cluster_config": { + "eds_config": { + "ads": {}, + "resource_api_version": "V3" + } + }, + "connect_timeout": "5s", + "circuit_breakers": {}, + "outlier_detection": {}, + "transport_socket": { + "name": "tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": {}, + "tls_certificates": [ + { + "certificate_chain": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + }, + "private_key": { + "inline_string": "[redacted]" + } + } + ], + "validation_context": { + "trusted_ca": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICEDCCAbWgAwIBAgIBBzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA1MTMwNDE4MDBa\nFw0zMjA1MTAwNDE4MDBaMDExLzAtBgNVBAMTJnByaS00OXhycXF6NC5jb25zdWwu\nY2EuYmMzODE1YzIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwQHp\nkEZUr0LVB1ng/zQMQyEQnID/wN/0+Ve648F3Lz4+S7D/S41EQ1Q9ImrNGIlmJ1b2\ncL9WcsL1A1/Ts8xNSaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkw\nKwYDVR0jBCQwIoAg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkx\nZjA4ZDAwLmNvbnN1bDAKBggqhkjOPQQDAgNJADBGAiEAhxIMzmCZT1sjtEKsjHIM\nC//yOo+pXZ62GQk+7rsE9HoCIQCxdLmYFUvOOiIXt4S15tvBpuJ6PdrKNlRTbmLx\nA5z5lQ==\n-----END CERTIFICATE-----\n" + }, + "match_subject_alt_names": [ + { + "exact": "spiffe://bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/ns/default/dc/dc1/svc/client" + } + ] + } + }, + "sni": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + }, + "common_lb_config": { + "healthy_panic_threshold": {} + }, + "alt_stat_name": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + }, + "last_updated": "2022-06-09T00:39:12.948Z" + }, + { + "version_info": "e0cc5c279829d13f01d2ba3a4d32546c0d3fc65b930bbb0bf66a68ad76e152a0", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + "type": "EDS", + "eds_cluster_config": { + "eds_config": { + "ads": {}, + "resource_api_version": "V3" + } + }, + "connect_timeout": "5s", + "circuit_breakers": {}, + "outlier_detection": {}, + "transport_socket": { + "name": "tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": {}, + "tls_certificates": [ + { + "certificate_chain": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + }, + "private_key": { + "inline_string": "[redacted]" + } + } + ], + "validation_context": { + "trusted_ca": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICEDCCAbWgAwIBAgIBBzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA1MTMwNDE4MDBa\nFw0zMjA1MTAwNDE4MDBaMDExLzAtBgNVBAMTJnByaS00OXhycXF6NC5jb25zdWwu\nY2EuYmMzODE1YzIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwQHp\nkEZUr0LVB1ng/zQMQyEQnID/wN/0+Ve648F3Lz4+S7D/S41EQ1Q9ImrNGIlmJ1b2\ncL9WcsL1A1/Ts8xNSaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkw\nKwYDVR0jBCQwIoAg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkx\nZjA4ZDAwLmNvbnN1bDAKBggqhkjOPQQDAgNJADBGAiEAhxIMzmCZT1sjtEKsjHIM\nC//yOo+pXZ62GQk+7rsE9HoCIQCxdLmYFUvOOiIXt4S15tvBpuJ6PdrKNlRTbmLx\nA5z5lQ==\n-----END CERTIFICATE-----\n" + }, + "match_subject_alt_names": [ + { + "exact": "spiffe://bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/ns/default/dc/dc1/svc/frontend" + } + ] + } + }, + "sni": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + }, + "common_lb_config": { + "healthy_panic_threshold": {} + }, + "alt_stat_name": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + }, + "last_updated": "2022-06-09T00:39:12.855Z" + }, + { + "version_info": "642b6322013fd3f776d9644ece515db5c4901fe6a87575ab4ff07498ab5faa47", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "local_app", + "type": "STATIC", + "connect_timeout": "5s", + "load_assignment": { + "cluster_name": "local_app", + "endpoints": [ + { + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 8080 + } + } + } + } + ] + } + ] + } + }, + "last_updated": "2022-05-13T04:22:39.655Z" + }, + { + "version_info": "dcd8d0247ba0149bfdc151428353b3f29d0665bf5c12af6a105a0abcc5af40ac", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "original-destination", + "type": "ORIGINAL_DST", + "connect_timeout": "5s", + "lb_policy": "CLUSTER_PROVIDED" + }, + "last_updated": "2022-05-13T04:22:39.743Z" + }, + { + "version_info": "1454ffe616e7abd2b3bec548b88f3a14c0500a94de27f2b3e8e3913e7bfd3275", + "cluster": { + "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", + "name": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + "type": "EDS", + "eds_cluster_config": { + "eds_config": { + "ads": {}, + "resource_api_version": "V3" + } + }, + "connect_timeout": "5s", + "circuit_breakers": {}, + "outlier_detection": {}, + "transport_socket": { + "name": "tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", + "common_tls_context": { + "tls_params": {}, + "tls_certificates": [ + { + "certificate_chain": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + }, + "private_key": { + "inline_string": "[redacted]" + } + } + ], + "validation_context": { + "trusted_ca": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICEDCCAbWgAwIBAgIBBzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA1MTMwNDE4MDBa\nFw0zMjA1MTAwNDE4MDBaMDExLzAtBgNVBAMTJnByaS00OXhycXF6NC5jb25zdWwu\nY2EuYmMzODE1YzIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwQHp\nkEZUr0LVB1ng/zQMQyEQnID/wN/0+Ve648F3Lz4+S7D/S41EQ1Q9ImrNGIlmJ1b2\ncL9WcsL1A1/Ts8xNSaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkw\nKwYDVR0jBCQwIoAg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkx\nZjA4ZDAwLmNvbnN1bDAKBggqhkjOPQQDAgNJADBGAiEAhxIMzmCZT1sjtEKsjHIM\nC//yOo+pXZ62GQk+7rsE9HoCIQCxdLmYFUvOOiIXt4S15tvBpuJ6PdrKNlRTbmLx\nA5z5lQ==\n-----END CERTIFICATE-----\n" + }, + "match_subject_alt_names": [ + { + "exact": "spiffe://bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/ns/default/dc/dc1/svc/server" + } + ] + } + }, + "sni": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + }, + "common_lb_config": { + "healthy_panic_threshold": {} + }, + "alt_stat_name": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + }, + "last_updated": "2022-06-09T00:39:12.754Z" + } + ] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.EndpointsConfigDump", + "static_endpoint_configs": [ + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "cluster_name": "local_agent", + "endpoints": [ + { + "locality": {}, + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.79.187", + "port_value": 8502 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + } + ] + } + ], + "policy": { + "overprovisioning_factor": 140 + } + } + } + ], + "dynamic_endpoint_configs": [ + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "cluster_name": "local_app", + "endpoints": [ + { + "locality": {}, + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 8080 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + } + ] + } + ], + "policy": { + "overprovisioning_factor": 140 + } + } + }, + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "endpoints": [ + { + "locality": {}, + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.31.201", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + }, + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.47.235", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + }, + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.71.254", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + } + ] + } + ], + "policy": { + "overprovisioning_factor": 140 + } + } + }, + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "endpoints": [ + { + "locality": {}, + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.63.120", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + } + ] + } + ], + "policy": { + "overprovisioning_factor": 140 + } + } + }, + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "endpoints": [ + { + "locality": {}, + "lb_endpoints": [ + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.18.110", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + }, + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.52.101", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + }, + { + "endpoint": { + "address": { + "socket_address": { + "address": "192.168.65.131", + "port_value": 20000 + } + }, + "health_check_config": {} + }, + "health_status": "HEALTHY", + "load_balancing_weight": 1 + } + ] + } + ], + "policy": { + "overprovisioning_factor": 140 + } + } + }, + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "cluster_name": "original-destination", + "policy": { + "overprovisioning_factor": 140 + } + } + } + ] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ListenersConfigDump", + "dynamic_listeners": [ + { + "name": "public_listener:192.168.69.179:20000", + "active_state": { + "version_info": "42e63fea110536be20b84ab28ef1979efb5e20b967a752b8834314c4fcd58358", + "listener": { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "public_listener:192.168.69.179:20000", + "address": { + "socket_address": { + "address": "192.168.69.179", + "port_value": 20000 + } + }, + "filter_chains": [ + { + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "public_listener", + "route_config": { + "name": "public_listener", + "virtual_hosts": [ + { + "name": "public_listener", + "domains": ["*"], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.rbac", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.rbac.v3.RBAC", + "rules": { + "action": "DENY", + "policies": { + "consul-intentions-layer4": { + "permissions": [ + { + "any": true + } + ], + "principals": [ + { + "authenticated": { + "principal_name": { + "safe_regex": { + "google_re2": {}, + "regex": "^spiffe://[^/]+/ns/default/dc/[^/]+/svc/client$" + } + } + } + } + ] + } + } + } + } + }, + { + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "random_sampling": {} + } + } + } + ], + "transport_socket": { + "name": "tls", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext", + "common_tls_context": { + "tls_params": {}, + "tls_certificates": [ + { + "certificate_chain": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + }, + "private_key": { + "inline_string": "[redacted]" + } + } + ], + "validation_context": { + "trusted_ca": { + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICEDCCAbWgAwIBAgIBBzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA1MTMwNDE4MDBa\nFw0zMjA1MTAwNDE4MDBaMDExLzAtBgNVBAMTJnByaS00OXhycXF6NC5jb25zdWwu\nY2EuYmMzODE1YzIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwQHp\nkEZUr0LVB1ng/zQMQyEQnID/wN/0+Ve648F3Lz4+S7D/S41EQ1Q9ImrNGIlmJ1b2\ncL9WcsL1A1/Ts8xNSaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkw\nKwYDVR0jBCQwIoAg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkx\nZjA4ZDAwLmNvbnN1bDAKBggqhkjOPQQDAgNJADBGAiEAhxIMzmCZT1sjtEKsjHIM\nC//yOo+pXZ62GQk+7rsE9HoCIQCxdLmYFUvOOiIXt4S15tvBpuJ6PdrKNlRTbmLx\nA5z5lQ==\n-----END CERTIFICATE-----\n" + } + } + }, + "require_client_certificate": true + } + } + } + ], + "traffic_direction": "INBOUND" + }, + "last_updated": "2022-06-09T00:39:27.668Z" + } + }, + { + "name": "outbound_listener:127.0.0.1:15001", + "active_state": { + "version_info": "2bce2cd7828d5b1adbd820824ce6948fdaa00b4c824cba5ba0932aea95b7f5cd", + "listener": { + "@type": "type.googleapis.com/envoy.config.listener.v3.Listener", + "name": "outbound_listener:127.0.0.1:15001", + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 15001 + } + }, + "filter_chains": [ + { + "filter_chain_match": { + "prefix_ranges": [ + { + "address_prefix": "10.100.134.173", + "prefix_len": 32 + }, + { + "address_prefix": "240.0.0.3", + "prefix_len": 32 + } + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "stat_prefix": "upstream.client.default.default.dc1", + "cluster": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + } + ] + }, + { + "filter_chain_match": { + "prefix_ranges": [ + { + "address_prefix": "10.100.254.176", + "prefix_len": 32 + }, + { + "address_prefix": "240.0.0.4", + "prefix_len": 32 + } + ] + }, + "filters": [ + { + "name": "envoy.filters.network.http_connection_manager", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + "stat_prefix": "upstream.server.default.default.dc1", + "route_config": { + "name": "server", + "virtual_hosts": [ + { + "name": "server.default.default.dc1", + "domains": ["*"], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + } + ] + } + ] + }, + "http_filters": [ + { + "name": "envoy.filters.http.router", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" + } + } + ], + "tracing": { + "random_sampling": {} + } + } + } + ] + }, + { + "filter_chain_match": { + "prefix_ranges": [ + { + "address_prefix": "10.100.31.2", + "prefix_len": 32 + }, + { + "address_prefix": "240.0.0.2", + "prefix_len": 32 + } + ] + }, + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "stat_prefix": "upstream.frontend.default.default.dc1", + "cluster": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + } + ] + }, + { + "filters": [ + { + "name": "envoy.filters.network.tcp_proxy", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + "stat_prefix": "upstream.original-destination", + "cluster": "original-destination" + } + } + ] + } + ], + "listener_filters": [ + { + "name": "envoy.filters.listener.original_dst", + "typed_config": { + "@type": "type.googleapis.com/envoy.extensions.filters.listener.original_dst.v3.OriginalDst" + } + } + ], + "traffic_direction": "OUTBOUND" + }, + "last_updated": "2022-05-24T17:41:59.079Z" + } + } + ] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.ScopedRoutesConfigDump" + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.RoutesConfigDump", + "static_route_configs": [ + { + "route_config": { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "public_listener", + "virtual_hosts": [ + { + "name": "public_listener", + "domains": ["*"], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "local_app" + } + } + ] + } + ] + }, + "last_updated": "2022-06-09T00:39:27.667Z" + }, + { + "route_config": { + "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", + "name": "server", + "virtual_hosts": [ + { + "name": "server.default.default.dc1", + "domains": ["*"], + "routes": [ + { + "match": { + "prefix": "/" + }, + "route": { + "cluster": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + } + } + ] + } + ] + }, + "last_updated": "2022-05-24T17:41:59.078Z" + } + ] + }, + { + "@type": "type.googleapis.com/envoy.admin.v3.SecretsConfigDump", + "static_secrets": [], + "dynamic_active_secrets": [ + { + "name": "default", + "secret": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "name": "default", + "tls_certificate": { + "certificate_chain": { + "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURQRENDQWlTZ0F3SUJBZ0lRTFNLbTFVWFVPWm5FdlllbjNLUWw4REFOQmdrcWhraUc5dzBCQVFzRkFEQVkKTVJZd0ZBWURWUVFLRXcxamJIVnpkR1Z5TG14dlkyRnNNQjRYRFRJeU1ETXhOVEExTVRJeU1sb1hEVEl5TURNeApOakExTVRReU1sb3dBRENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFOYWFYMzlyCmppRU9pU3plK0hlSm42dmJxMnhHQW1aNEdHS04rQXZzWnMrbEIza3dmOXhZaWh5WHlIcHpXZ2VuRy9pazl3dGMKYTNURWZiMktZMVBIWXRzK2JtV2pwcU8xY2xacFNib1ZQWCtMYllsQmFSeDhVZWo5bENxOXJxRWVoTkt5K3AweQpzVmg2WVhlTjlxaWNEWGZzTnowdDZmNVMraW5LY0VCYzAwVGFUSEtReEs0VEh4R296SmxBMi9EeGNJc0tNdXB5CjAxZ1BXdXpWWHp6b1JwTTdKandRd0hGU3RBdy9TOHo0ZHhtZkd3aTl3Q0U0T1FRVmYwSFJpZ1ZiTUd0NUF1dkcKMXF3Q1Y3eVY5WW92a0pvbzhmSytqdDdrd1pLRFpWcDlvMDB4YkM4NzNwNnI0M05hd2lXOGJQNGNqNS9ob0xLUApGUTJuYmRmTGRFaUlYSzhDQXdFQUFhT0JtVENCbGpBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGxCQll3CkZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVUKRVI5T2JmWkhhWjh2NldZa281T2FPa28rczhnd05nWURWUjBSQVFIL0JDd3dLb1lvYzNCcFptWmxPaTh2WTJ4MQpjM1JsY2k1c2IyTmhiQzl1Y3k5bWIyOHZjMkV2WkdWbVlYVnNkREFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBClN2SmRPcmJxWk1KUTFTQlpEUG11V3pmbEJXSEgrWVhJMVZRK1ZiaWZmQmJveHJTNlZuaDZVNEZKRHZsWTNSQWgKVDJES09MaVVySWVXY0tlMTlXajdVSDB6MVJPbXFvQ2YvazlPNWZqVDl0WGRTZVBmNjd0d2lMUWpXUklaQVJuMwpMTGlXaTMwQmpSWDEwSy9GS2pTaWRBbVZIVDZRT3AvcTEzSTE0Z2VaL0NPeThTd1pwZ2ZGN2RxY0RERjJwZ3ovCk4xSE8yLzJrbjhrWGNuNUZLWTRaNWh3RWlQOUlPOGVmSzIvNkMzSzkvOFJPNGdNWlZLTW9JVEUyZS84eW03Tm0KaVdyZHdvaWdLN0J5di9tMkVvWWdjb01vaDhkWnczMU9ZMUl4T1hqR1NIdVF2NWZzWlNObG1NaDNSbVlaVFY3dwpBSUZuWUc4QWlPV2hRd2JMUVRBc1lRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQotLS0tLUJFR0lOIENFUlRJRklDQVRFLS0tLS0KTUlJQy9UQ0NBZVdnQXdJQkFnSVJBS2IreFppZHE2bTFFbllpTllsVXBWY3dEUVlKS29aSWh2Y05BUUVMQlFBdwpHREVXTUJRR0ExVUVDaE1OWTJ4MWMzUmxjaTVzYjJOaGJEQWVGdzB5TWpBek1UVXdOVEV4TVRaYUZ3MHpNakF6Ck1USXdOVEV4TVRaYU1CZ3hGakFVQmdOVkJBb1REV05zZFhOMFpYSXViRzlqWVd3d2dnRWlNQTBHQ1NxR1NJYjMKRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEUllRNVowMGk4MVdmQzF5ZmZ6dFlhbmF5U3U3Ym5CT3BEQ2ttNwo5azZuTlBwZ1luRWU3U1QzL2l1N0xIUWI0bzdKSlFnVkZhNWhON3Bqa1R0QU11ZE5scVByNEp5SCs0dDU0RzVTCndjUk5vYjg1dVFFS0dldnRDYzlFcmROcEZJREpwREViWUhKZjVQWHZ0UTQ5bW9mc09GS2hxVzdyMCtJTWUwZmoKZUZPYUg5MXdOVEdyRnJpTEgyQ2s2Mk1ZYmpRcGVjRjEydkFRTzdvRitkd1BlOWVYLzJPNWFsOWdDcXhtdGFVTwpFbXBGWktCYUxIUHFSbVNzbEhVUW14R3A0RlJ5S21uVnE4ZHR3Rm00TGJ1dHhVckZYOWt4N0FENkFoZUJITTRCCkd2eEZ1YTV1YTlQdjVHWGdTaVE5aXp6Y2l2ZE5RMm45a1QxUGFBenV0cDhnbFZVYkFnTUJBQUdqUWpCQU1BNEcKQTFVZER3RUIvd1FFQXdJQ0JEQVBCZ05WSFJNQkFmOEVCVEFEQVFIL01CMEdBMVVkRGdRV0JCUVJIMDV0OWtkcApueS9wWmlTams1bzZTajZ6eURBTkJna3Foa2lHOXcwQkFRc0ZBQU9DQVFFQXpHR1NjVGt3c01IcVBhU3RONVJ2CnJBNmVRVENuS2lOdDdiQjVBYjJwZEdrMHc2V1Y1RkZVdDZZdFRZK1BjMlY1RXAyd0JwaUxST1EzQnVBS3JFRnoKYW10dWtsb1pSWFZHTm14emcwYUNkNGxpYVNhZTM2aTJaN0NZczZZWnZSMGhJNWtuTHd0WTNRbzBOM3UyUVQzYQo4blJ0bjZqNjhadlQxV2xWazVFTFJZTEVYQzFtK3JQcEZXU0xoQkJ2N3lZR29qd0tTUFV5ZXV4YmpBc3pUR3VrCnQ1anNybEpBcFhBUDkyNTRFdFFWUjltY24ySThQd0lTVnpFUzlDRUtXT0hGUWdwS1BpVFM2SFlOWWUwSzZxQmcKWlBwaHFPNUJKRnVNVnhXWlNEMkZPYUQybmNoMm80KzJiMDF1ZTRvaDRnMWkyRWlZZ1FjcjRmRDA5V3Q4Q0NsYwpIQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K" + }, + "private_key": { + "inline_bytes": "[redacted]" + } + } + }, + "last_updated": "2022-05-24T17:41:59.078Z" + } + ], + "dynamic_warming_secrets": [ + { + "name": "ROOTCA", + "last_updated": "2022-03-15T05:14:22.868Z", + "secret": { + "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.Secret", + "name": "ROOTCA", + "validation_context": { + "trusted_ca": { + "inline_bytes": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMvVENDQWVXZ0F3SUJBZ0lSQUtiK3haaWRxNm0xRW5ZaU5ZbFVwVmN3RFFZSktvWklodmNOQVFFTEJRQXcKR0RFV01CUUdBMVVFQ2hNTlkyeDFjM1JsY2k1c2IyTmhiREFlRncweU1qQXpNVFV3TlRFeE1UWmFGdzB6TWpBegpNVEl3TlRFeE1UWmFNQmd4RmpBVUJnTlZCQW9URFdOc2RYTjBaWEl1Ykc5allXd3dnZ0VpTUEwR0NTcUdTSWIzCkRRRUJBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRFJZUTVaMDBpODFXZkMxeWZmenRZYW5heVN1N2JuQk9wRENrbTcKOWs2bk5QcGdZbkVlN1NUMy9pdTdMSFFiNG83SkpRZ1ZGYTVoTjdwamtUdEFNdWRObHFQcjRKeUgrNHQ1NEc1Uwp3Y1JOb2I4NXVRRUtHZXZ0Q2M5RXJkTnBGSURKcERFYllISmY1UFh2dFE0OW1vZnNPRktocVc3cjArSU1lMGZqCmVGT2FIOTF3TlRHckZyaUxIMkNrNjJNWWJqUXBlY0YxMnZBUU83b0YrZHdQZTllWC8yTzVhbDlnQ3F4bXRhVU8KRW1wRlpLQmFMSFBxUm1Tc2xIVVFteEdwNEZSeUttblZxOGR0d0ZtNExidXR4VXJGWDlreDdBRDZBaGVCSE00QgpHdnhGdWE1dWE5UHY1R1hnU2lROWl6emNpdmROUTJuOWtUMVBhQXp1dHA4Z2xWVWJBZ01CQUFHalFqQkFNQTRHCkExVWREd0VCL3dRRUF3SUNCREFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQjBHQTFVZERnUVdCQlFSSDA1dDlrZHAKbnkvcFppU2prNW82U2o2enlEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUF6R0dTY1Rrd3NNSHFQYVN0TjVSdgpyQTZlUVRDbktpTnQ3YkI1QWIycGRHazB3NldWNUZGVXQ2WXRUWStQYzJWNUVwMndCcGlMUk9RM0J1QUtyRUZ6CmFtdHVrbG9aUlhWR05teHpnMGFDZDRsaWFTYWUzNmkyWjdDWXM2WVp2UjBoSTVrbkx3dFkzUW8wTjN1MlFUM2EKOG5SdG42ajY4WnZUMVdsVms1RUxSWUxFWEMxbStyUHBGV1NMaEJCdjd5WUdvandLU1BVeWV1eGJqQXN6VEd1awp0NWpzcmxKQXBYQVA5MjU0RXRRVlI5bWNuMkk4UHdJU1Z6RVM5Q0VLV09IRlFncEtQaVRTNkhZTlllMEs2cUJnClpQcGhxTzVCSkZ1TVZ4V1pTRDJGT2FEMm5jaDJvNCsyYjAxdWU0b2g0ZzFpMkVpWWdRY3I0ZkQwOVd0OENDbGMKSEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t" + } + } + } + } + ] + } + ] +} diff --git a/cli/cmd/status/status.go b/cli/cmd/status/status.go index 5c148e9921..926d8d790b 100644 --- a/cli/cmd/status/status.go +++ b/cli/cmd/status/status.go @@ -52,9 +52,6 @@ func (c *Command) init() { }) c.help = c.set.Help() - - // c.Init() calls the embedded BaseCommand's initialization function. - c.Init() } // Run checks the status of a Consul installation on Kubernetes. @@ -152,33 +149,10 @@ func (c *Command) checkHelmInstallation(settings *helmCLI.EnvSettings, uiLogger timezone, _ := rel.Info.LastDeployed.Zone() - tbl := terminal.NewTable([]string{"Name", "Namespace", "Status", "Chart Version", "AppVersion", "Revision", "Last Updated"}...) - trow := []terminal.TableEntry{ - { - Value: releaseName, - }, - { - Value: namespace, - }, - { - Value: string(rel.Info.Status), - }, - { - Value: rel.Chart.Metadata.Version, - }, - { - Value: rel.Chart.Metadata.AppVersion, - }, - { - Value: strconv.Itoa(rel.Version), - }, - { - Value: rel.Info.LastDeployed.Format("2006/01/02 15:04:05") + " " + timezone, - }, - } - tbl.Rows = [][]terminal.TableEntry{} - tbl.Rows = append(tbl.Rows, trow) - + tbl := terminal.NewTable("Name", "Namespace", "Status", "Chart Version", "AppVersion", "Revision", "Last Updated") + tbl.AddRow([]string{releaseName, namespace, string(rel.Info.Status), rel.Chart.Metadata.Version, + rel.Chart.Metadata.AppVersion, strconv.Itoa(rel.Version), + rel.Info.LastDeployed.Format("2006/01/02 15:04:05") + " " + timezone}, []string{}) c.UI.Table(tbl) valuesYaml, err := yaml.Marshal(rel.Config) diff --git a/cli/cmd/uninstall/uninstall.go b/cli/cmd/uninstall/uninstall.go index 288f97823b..01a442226d 100644 --- a/cli/cmd/uninstall/uninstall.go +++ b/cli/cmd/uninstall/uninstall.go @@ -105,9 +105,6 @@ func (c *Command) init() { }) c.help = c.set.Help() - - // c.Init() calls the embedded BaseCommand's initialization function. - c.Init() } func (c *Command) Run(args []string) int { diff --git a/cli/cmd/uninstall/uninstall_test.go b/cli/cmd/uninstall/uninstall_test.go index 8f1df8de80..7d36ce5d3d 100644 --- a/cli/cmd/uninstall/uninstall_test.go +++ b/cli/cmd/uninstall/uninstall_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/hashicorp/consul-k8s/cli/common" + "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/require" batchv1 "k8s.io/api/batch/v1" @@ -356,6 +357,7 @@ func getInitializedCommand(t *testing.T) *Command { baseCommand := &common.BaseCommand{ Log: log, + UI: terminal.NewBasicUI(context.TODO()), } c := &Command{ diff --git a/cli/cmd/upgrade/upgrade.go b/cli/cmd/upgrade/upgrade.go index 4ef26661e8..e145e238e1 100644 --- a/cli/cmd/upgrade/upgrade.go +++ b/cli/cmd/upgrade/upgrade.go @@ -157,9 +157,6 @@ func (c *Command) init() { }) c.help = c.set.Help() - - // c.Init() calls the embedded BaseCommand's initialization function. - c.Init() } func (c *Command) Run(args []string) int { diff --git a/cli/cmd/version/version.go b/cli/cmd/version/version.go index b8b2235f46..f31fa711f1 100644 --- a/cli/cmd/version/version.go +++ b/cli/cmd/version/version.go @@ -1,8 +1,6 @@ package version import ( - "sync" - "github.com/hashicorp/consul-k8s/cli/common" "github.com/hashicorp/consul-k8s/cli/common/terminal" ) @@ -12,17 +10,10 @@ type Command struct { // Version is the Consul on Kubernetes CLI version. Version string - - once sync.Once -} - -func (c *Command) init() { - c.Init() } // Run prints the version of the Consul on Kubernetes CLI. func (c *Command) Run(_ []string) int { - c.once.Do(c.init) c.UI.Output("consul-k8s %s", c.Version, terminal.WithInfoStyle()) return 0 } diff --git a/cli/commands.go b/cli/commands.go index 681421c502..d29b4a8ad7 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -4,11 +4,15 @@ import ( "context" "github.com/hashicorp/consul-k8s/cli/cmd/install" + "github.com/hashicorp/consul-k8s/cli/cmd/proxy" + "github.com/hashicorp/consul-k8s/cli/cmd/proxy/list" + "github.com/hashicorp/consul-k8s/cli/cmd/proxy/read" "github.com/hashicorp/consul-k8s/cli/cmd/status" "github.com/hashicorp/consul-k8s/cli/cmd/uninstall" "github.com/hashicorp/consul-k8s/cli/cmd/upgrade" cmdversion "github.com/hashicorp/consul-k8s/cli/cmd/version" "github.com/hashicorp/consul-k8s/cli/common" + "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/consul-k8s/cli/version" "github.com/hashicorp/go-hclog" "github.com/mitchellh/cli" @@ -19,6 +23,7 @@ func initializeCommands(ctx context.Context, log hclog.Logger) (*common.BaseComm baseCommand := &common.BaseCommand{ Ctx: ctx, Log: log, + UI: terminal.NewBasicUI(ctx), } commands := map[string]cli.CommandFactory{ @@ -48,6 +53,21 @@ func initializeCommands(ctx context.Context, log hclog.Logger) (*common.BaseComm Version: version.GetHumanVersion(), }, nil }, + "proxy": func() (cli.Command, error) { + return &proxy.ProxyCommand{ + BaseCommand: baseCommand, + }, nil + }, + "proxy list": func() (cli.Command, error) { + return &list.ListCommand{ + BaseCommand: baseCommand, + }, nil + }, + "proxy read": func() (cli.Command, error) { + return &read.ReadCommand{ + BaseCommand: baseCommand, + }, nil + }, } return baseCommand, commands diff --git a/cli/common/base.go b/cli/common/base.go index 81bb360267..2237b66f84 100644 --- a/cli/common/base.go +++ b/cli/common/base.go @@ -36,9 +36,3 @@ func (c *BaseCommand) Close() error { return nil } - -// Init should be called FIRST within the Run function implementation. -func (c *BaseCommand) Init() { - ui := terminal.NewBasicUI(c.Ctx) - c.UI = ui -} diff --git a/cli/common/flag/set.go b/cli/common/flag/set.go index df44e7031c..94c8e184c2 100644 --- a/cli/common/flag/set.go +++ b/cli/common/flag/set.go @@ -56,6 +56,22 @@ func (f *Sets) NewSet(name string) *Set { return flagSet } +// GetSetFlags returns a slice of flags for a given set. +// If the requested set does not exist, this will return an empty slice. +func (f *Sets) GetSetFlags(setName string) []string { + var setFlags []string + for _, set := range f.flagSets { + if set.name == setName { + set.flagSet.VisitAll(func(f *flag.Flag) { + setFlags = append(setFlags, fmt.Sprintf("-%s", f.Name)) + }) + return setFlags + } + } + + return setFlags +} + // Completions returns the completions for this flag set. func (f *Sets) Completions() complete.Flags { return f.completions diff --git a/cli/common/portforward.go b/cli/common/portforward.go new file mode 100644 index 0000000000..a2acd02d27 --- /dev/null +++ b/cli/common/portforward.go @@ -0,0 +1,141 @@ +package common + +import ( + "context" + "fmt" + "io" + "net" + "net/http" + "net/url" + "strconv" + "time" + + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/portforward" + "k8s.io/client-go/transport/spdy" +) + +// PortForward represents a Kubernetes Pod port forwarding session which can be +// run as a background process. +type PortForward struct { + // Namespace is the Kubernetes Namespace where the Pod can be found. + Namespace string + // PodName is the name of the Pod to port forward. + PodName string + // RemotePort is the port on the Pod to forward to. + RemotePort int + + // KubeClient is the Kubernetes Client to use for port forwarding. + KubeClient kubernetes.Interface + // RestConfig is the REST client configuration to use for port forwarding. + RestConfig *rest.Config + + localPort int + stopChan chan struct{} + readyChan chan struct{} + + portForwardURL *url.URL + newForwarder func(httpstream.Dialer, []string, <-chan struct{}, chan struct{}, io.Writer, io.Writer) (forwarder, error) +} + +// PortForwarder enables a user to open and close a connection to a remote server. +type PortForwarder interface { + Open(context.Context) (string, error) + Close() +} + +// forwarder is an interface which can be used for opening a port forward session. +type forwarder interface { + ForwardPorts() error + Close() + GetPorts() ([]portforward.ForwardedPort, error) +} + +// Open opens a port forward session to a Kubernetes Pod. +func (pf *PortForward) Open(ctx context.Context) (string, error) { + // Get an open port on localhost. + if err := pf.allocateLocalPort(); err != nil { + return "", fmt.Errorf("failed to allocate local port: %v", err) + } + + // Configure the URL for starting the port forward. + if pf.portForwardURL == nil { + pf.portForwardURL = pf.KubeClient.CoreV1().RESTClient().Post().Resource("pods").Namespace(pf.Namespace). + Name(pf.PodName).SubResource("portforward").URL() + } + + // Create a dialer for the port forward target. + transport, upgrader, err := spdy.RoundTripperFor(pf.RestConfig) + if err != nil { + return "", fmt.Errorf("failed to create roundtripper: %v", err) + } + dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, "POST", pf.portForwardURL) + + // Create channels for Goroutines to communicate. + pf.stopChan = make(chan struct{}, 1) + pf.readyChan = make(chan struct{}, 1) + errChan := make(chan error) + + // Use the default Kubernetes port forwarder if none is specified. + if pf.newForwarder == nil { + pf.newForwarder = newDefaultForwarder + } + + // Create a Kubernetes port forwarder. + ports := []string{fmt.Sprintf("%d:%d", pf.localPort, pf.RemotePort)} + portforwarder, err := pf.newForwarder(dialer, ports, pf.stopChan, pf.readyChan, nil, nil) + if err != nil { + return "", err + } + + // Start port forwarding. + go func() { + errChan <- portforwarder.ForwardPorts() + }() + + select { + case <-pf.readyChan: + return fmt.Sprintf("localhost:%d", pf.localPort), nil + case err := <-errChan: + return "", err + case <-ctx.Done(): + pf.Close() + return "", fmt.Errorf("port forward cancelled") + case <-time.After(time.Second * 5): + pf.Close() + return "", fmt.Errorf("port forward timed out") + } +} + +// Close closes the port forward connection. +func (pf *PortForward) Close() { + close(pf.stopChan) +} + +// allocateLocalPort looks for an open port on localhost and sets it to the +// localPort field. +func (pf *PortForward) allocateLocalPort() error { + listener, err := net.Listen("tcp", ":0") + if err != nil { + return err + } + + _, port, err := net.SplitHostPort(listener.Addr().String()) + if err != nil { + return err + } + + if err := listener.Close(); err != nil { + return fmt.Errorf("unable to close listener %v", err) + } + + pf.localPort, err = strconv.Atoi(port) + return err +} + +// newDefaultForwarder creates a new Kubernetes port forwarder. +func newDefaultForwarder(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, readyChan chan struct{}, out, errOut io.Writer) (forwarder, error) { + return portforward.New(dialer, ports, stopChan, readyChan, out, errOut) +} diff --git a/cli/common/portforward_test.go b/cli/common/portforward_test.go new file mode 100644 index 0000000000..9bf7cf8e9d --- /dev/null +++ b/cli/common/portforward_test.go @@ -0,0 +1,127 @@ +package common + +import ( + "context" + "fmt" + "io" + "net/url" + "testing" + "time" + + "github.com/stretchr/testify/require" + "k8s.io/apimachinery/pkg/util/httpstream" + "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/portforward" +) + +type mockForwarder struct { + forwardBehavior func() error +} + +func (m *mockForwarder) ForwardPorts() error { return m.forwardBehavior() } +func (m *mockForwarder) Close() {} +func (m *mockForwarder) GetPorts() ([]portforward.ForwardedPort, error) { return nil, nil } + +func TestPortForwardingSuccess(t *testing.T) { + mockForwarder := &mockForwarder{ + forwardBehavior: func() error { return nil }, + } + + newMockForwarder := func(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, readyChan chan struct{}, out, errOut io.Writer) (forwarder, error) { + close(readyChan) + return mockForwarder, nil + } + + pf := &PortForward{ + KubeClient: fake.NewSimpleClientset(), + RestConfig: &rest.Config{}, + portForwardURL: &url.URL{}, + newForwarder: newMockForwarder, + } + + endpoint, err := pf.Open(context.Background()) + defer pf.Close() + + require.NoError(t, err) + require.Equal(t, fmt.Sprintf("localhost:%d", pf.localPort), endpoint) +} + +func TestPortForwardingError(t *testing.T) { + mockForwarder := &mockForwarder{ + forwardBehavior: func() error { + return fmt.Errorf("error") + }, + } + + newMockForwarder := func(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, readyChan chan struct{}, out, errOut io.Writer) (forwarder, error) { + return mockForwarder, nil + } + + pf := &PortForward{ + KubeClient: fake.NewSimpleClientset(), + RestConfig: &rest.Config{}, + portForwardURL: &url.URL{}, + newForwarder: newMockForwarder, + } + + endpoint, err := pf.Open(context.Background()) + defer pf.Close() + + require.Error(t, err) + require.Equal(t, "error", err.Error()) + require.Equal(t, "", endpoint) +} + +func TestPortForwardingContextCancel(t *testing.T) { + mockForwarder := &mockForwarder{ + forwardBehavior: func() error { + return nil + }, + } + + newMockForwarder := func(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, readyChan chan struct{}, out, errOut io.Writer) (forwarder, error) { + return mockForwarder, nil + } + + pf := &PortForward{ + KubeClient: fake.NewSimpleClientset(), + RestConfig: &rest.Config{}, + portForwardURL: &url.URL{}, + newForwarder: newMockForwarder, + } + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + endpoint, err := pf.Open(ctx) + + require.Error(t, err) + require.Equal(t, "port forward cancelled", err.Error()) + require.Equal(t, "", endpoint) +} + +func TestPortForwardingTimeout(t *testing.T) { + mockForwarder := &mockForwarder{ + forwardBehavior: func() error { + time.Sleep(time.Second * 10) + return nil + }, + } + + newMockForwarder := func(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, readyChan chan struct{}, out, errOut io.Writer) (forwarder, error) { + return mockForwarder, nil + } + + pf := &PortForward{ + KubeClient: fake.NewSimpleClientset(), + RestConfig: &rest.Config{}, + portForwardURL: &url.URL{}, + newForwarder: newMockForwarder, + } + + endpoint, err := pf.Open(context.Background()) + + require.Error(t, err) + require.Equal(t, "port forward timed out", err.Error()) + require.Equal(t, "", endpoint) +} diff --git a/cli/common/terminal/basic.go b/cli/common/terminal/basic.go index d06815b8f5..e8411b9aec 100644 --- a/cli/common/terminal/basic.go +++ b/cli/common/terminal/basic.go @@ -15,15 +15,22 @@ import ( "github.com/mattn/go-isatty" ) -// basicUI. +// basicUI is a standard implementation of the UI interface for the terminal. type basicUI struct { - ctx context.Context + ctx context.Context + bufOut io.Writer } +// NewBasicUI creates a new instance of the basicUI struct for the terminal +// with color output. func NewBasicUI(ctx context.Context) *basicUI { - return &basicUI{ - ctx: ctx, - } + return NewUI(ctx, color.Output) +} + +// NewUI creates a new instance of the basicUI struct that outputs to +// the bufOut buffer. +func NewUI(ctx context.Context, bufOut io.Writer) *basicUI { + return &basicUI{ctx: ctx, bufOut: bufOut} } // Input implements UI. @@ -32,8 +39,8 @@ func (ui *basicUI) Input(input *Input) (string, error) { // Write the prompt, add a space. ui.Output(input.Prompt, WithStyle(input.Style), WithWriter(&buf)) - fmt.Fprint(color.Output, strings.TrimRight(buf.String(), "\r\n")) - fmt.Fprint(color.Output, " ") + fmt.Fprint(ui.bufOut, strings.TrimRight(buf.String(), "\r\n")) + fmt.Fprint(ui.bufOut, " ") // Ask for input in a go-routine so that we can ignore it. errCh := make(chan error, 1) @@ -62,7 +69,7 @@ func (ui *basicUI) Input(input *Input) (string, error) { return line, nil case <-ui.ctx.Done(): // Print newline so that any further output starts properly - fmt.Fprintln(color.Output) + fmt.Fprintln(ui.bufOut) return "", ui.ctx.Err() } } @@ -74,7 +81,7 @@ func (ui *basicUI) Interactive() bool { // Output implements UI. func (ui *basicUI) Output(msg string, raw ...interface{}) { - msg, style, w := Interpret(msg, raw...) + msg, style, w := ui.parse(msg, raw...) switch style { case HeaderStyle: @@ -114,7 +121,10 @@ func (ui *basicUI) Output(msg string, raw ...interface{}) { // NamedValues implements UI. func (ui *basicUI) NamedValues(rows []NamedValue, opts ...Option) { - cfg := &config{Writer: color.Output} + cfg := &config{ + Writer: ui.bufOut, + Style: "", + } for _, opt := range opts { opt(cfg) } @@ -147,3 +157,31 @@ func (ui *basicUI) NamedValues(rows []NamedValue, opts ...Option) { func (ui *basicUI) OutputWriters() (io.Writer, io.Writer, error) { return os.Stdout, os.Stderr, nil } + +// parse decomposes the msg and arguments into the message, style, and writer. +func (ui *basicUI) parse(msg string, raw ...interface{}) (string, string, io.Writer) { + // Build our args and options + var args []interface{} + var opts []Option + for _, r := range raw { + if opt, ok := r.(Option); ok { + opts = append(opts, opt) + } else { + args = append(args, r) + } + } + + // Build our message + msg = fmt.Sprintf(msg, args...) + + // Build our config and set our options + cfg := &config{ + Writer: ui.bufOut, + Style: "", + } + for _, opt := range opts { + opt(cfg) + } + + return msg, cfg.Style, cfg.Writer +} diff --git a/cli/common/terminal/table.go b/cli/common/terminal/table.go index c8e8c2c67b..67278931a4 100644 --- a/cli/common/terminal/table.go +++ b/cli/common/terminal/table.go @@ -1,14 +1,31 @@ package terminal import ( - "github.com/fatih/color" "github.com/olekukonko/tablewriter" ) +const ( + Yellow = "yellow" + Green = "green" + Red = "red" +) + +var colorMapping = map[string]int{ + Green: tablewriter.FgGreenColor, + Yellow: tablewriter.FgYellowColor, + Red: tablewriter.FgRedColor, +} + // Passed to UI.Table to provide a nicely formatted table. type Table struct { Headers []string - Rows [][]TableEntry + Rows [][]Cell +} + +// Cell is a single entry for a table. +type Cell struct { + Value string + Color string } // Table creates a new Table structure that can be used with UI.Table. @@ -18,21 +35,15 @@ func NewTable(headers ...string) *Table { } } -// TableEntry is a single entry for a table. -type TableEntry struct { - Value string - Color string -} - -// Rich adds a row to the table. -func (t *Table) Rich(cols []string, colors []string) { - var row []TableEntry +// AddRow adds a row to the table. +func (t *Table) AddRow(cols []string, colors []string) { + var row []Cell for i, col := range cols { if i < len(colors) { - row = append(row, TableEntry{Value: col, Color: colors[i]}) + row = append(row, Cell{Value: col, Color: colors[i]}) } else { - row = append(row, TableEntry{Value: col}) + row = append(row, Cell{Value: col}) } } @@ -42,7 +53,7 @@ func (t *Table) Rich(cols []string, colors []string) { // Table implements UI. func (u *basicUI) Table(tbl *Table, opts ...Option) { // Build our config and set our options - cfg := &config{Writer: color.Output} + cfg := &config{Writer: u.bufOut} for _, opt := range opts { opt(cfg) } @@ -52,20 +63,15 @@ func (u *basicUI) Table(tbl *Table, opts ...Option) { table.SetHeader(tbl.Headers) table.SetBorder(false) table.SetAutoWrapText(false) - - if cfg.Style == "Simple" { - // Format the table without borders, simple output - - table.SetAutoFormatHeaders(true) - table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) - table.SetAlignment(tablewriter.ALIGN_LEFT) - table.SetCenterSeparator("") - table.SetColumnSeparator("") - table.SetRowSeparator("") - table.SetHeaderLine(false) - table.SetTablePadding("\t") // pad with tabs - table.SetNoWhiteSpace(true) - } + table.SetAutoFormatHeaders(false) + table.SetHeaderAlignment(tablewriter.ALIGN_LEFT) + table.SetAlignment(tablewriter.ALIGN_LEFT) + table.SetCenterSeparator("") + table.SetColumnSeparator("") + table.SetRowSeparator("") + table.SetHeaderLine(false) + table.SetTablePadding("\t") // pad with tabs + table.SetNoWhiteSpace(true) for _, row := range tbl.Rows { colors := make([]tablewriter.Colors, len(row)) @@ -85,15 +91,3 @@ func (u *basicUI) Table(tbl *Table, opts ...Option) { table.Render() } - -const ( - Yellow = "yellow" - Green = "green" - Red = "red" -) - -var colorMapping = map[string]int{ - Green: tablewriter.FgGreenColor, - Yellow: tablewriter.FgYellowColor, - Red: tablewriter.FgRedColor, -} diff --git a/cli/common/terminal/ui.go b/cli/common/terminal/ui.go index a9baa7aa87..b90d05b197 100644 --- a/cli/common/terminal/ui.go +++ b/cli/common/terminal/ui.go @@ -2,7 +2,6 @@ package terminal import ( "errors" - "fmt" "io" "github.com/fatih/color" @@ -66,31 +65,6 @@ type Input struct { Secret bool } -// Interpret decomposes the msg and arguments into the message, style, and writer. -func Interpret(msg string, raw ...interface{}) (string, string, io.Writer) { - // Build our args and options - var args []interface{} - var opts []Option - for _, r := range raw { - if opt, ok := r.(Option); ok { - opts = append(opts, opt) - } else { - args = append(args, r) - } - } - - // Build our message - msg = fmt.Sprintf(msg, args...) - - // Build our config and set our options - cfg := &config{Writer: color.Output} - for _, opt := range opts { - opt(cfg) - } - - return msg, cfg.Style, cfg.Writer -} - const ( HeaderStyle = "header" ErrorStyle = "error" diff --git a/cli/go.mod b/cli/go.mod index c8807e4be5..00c718a139 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -20,6 +20,7 @@ require ( k8s.io/apimachinery v0.22.2 k8s.io/cli-runtime v0.21.0 k8s.io/client-go v0.22.2 + k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a sigs.k8s.io/yaml v1.2.0 ) @@ -140,8 +141,8 @@ require ( golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/appengine v1.6.5 // indirect google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect - google.golang.org/grpc v1.33.1 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/grpc v1.36.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/gorp.v1 v1.7.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect @@ -152,7 +153,6 @@ require ( k8s.io/klog/v2 v2.9.0 // indirect k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect k8s.io/kubectl v0.21.0 // indirect - k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect rsc.io/letsencrypt v0.0.3 // indirect sigs.k8s.io/kustomize/api v0.8.5 // indirect sigs.k8s.io/kustomize/kyaml v0.10.15 // indirect diff --git a/cli/go.sum b/cli/go.sum index c24ee30004..d65d9b4ff1 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -144,7 +144,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk= @@ -225,7 +225,7 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -1129,8 +1129,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1 h1:DGeFlSan2f+WEtCERJ4J9GJWk15TxUi8QGagfI87Xyc= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1142,8 +1142,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From 4c3ec61833915656a1ddd63202097a0e9df6e3ee Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Tue, 9 Aug 2022 15:36:36 -0700 Subject: [PATCH 072/235] peering: update unit tests to not reuse peering token to be compatible with consul 1.13 (#1401) -and bump unit test consul version to 1.13 --- .github/workflows/test.yml | 14 +-- .../peering_dialer_controller.go | 4 +- .../peering_dialer_controller_test.go | 85 +++++++------------ 3 files changed, 42 insertions(+), 61 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d962e5f33c..6b90795000 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,8 +4,8 @@ on: env: TEST_RESULTS: /tmp/test-results # path to where test results are saved - CONSUL_VERSION: 1.13.0-alpha2 # Consul's OSS version to use in tests - CONSUL_ENT_VERSION: 1.13.0-alpha2+ent # Consul's enterprise version to use in tests + CONSUL_VERSION: 1.13.0 # Consul's OSS version to use in tests + CONSUL_ENT_VERSION: 1.13.0+ent # Consul's enterprise version to use in tests GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. jobs: @@ -146,8 +146,9 @@ jobs: working-directory: control-plane run: | mkdir -p $HOME/bin - wget https://github.com/ndhanushkodi/binaries/releases/download/v4.1oss/consul -O consulbin && \ - mv consulbin $HOME/bin/consul && + wget https://releases.hashicorp.com/consul/${{env.CONSUL_VERSION}}/consul_${{env.CONSUL_VERSION}}_linux_amd64.zip && \ + unzip consul_${{env.CONSUL_VERSION}}_linux_amd64.zip -d $HOME/bin && \ + rm consul_${{env.CONSUL_VERSION}}_linux_amd64.zip chmod +x $HOME/bin/consul - name: Run go tests @@ -194,8 +195,9 @@ jobs: working-directory: control-plane run: | mkdir -p $HOME/bin - wget https://github.com/ndhanushkodi/binaries/releases/download/v4.1ent/consul -O consulbin && \ - mv consulbin $HOME/bin/consul && + wget https://releases.hashicorp.com/consul/${{env.CONSUL_ENT_VERSION}}/consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip && \ + unzip consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip -d $HOME/bin && \ + rm consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip chmod +x $HOME/bin/consul - name: Run go tests diff --git a/control-plane/connect-inject/peering_dialer_controller.go b/control-plane/connect-inject/peering_dialer_controller.go index 29273b14ba..0ed3dacea2 100644 --- a/control-plane/connect-inject/peering_dialer_controller.go +++ b/control-plane/connect-inject/peering_dialer_controller.go @@ -152,7 +152,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques // Or, if the peering in Consul does exist, compare it to the spec's secret. If there's any // differences, initiate peering. if r.specStatusSecretsDifferent(dialer, specSecret) { - r.Log.Info("the version annotation was incremented; re-establishing peering with spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) + r.Log.Info("the spec.peer.secret is different from the status secret, re-establishing peering", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { r.updateStatusError(ctx, dialer, ConsulAgentError, err) @@ -164,7 +164,7 @@ func (r *PeeringDialerController) Reconcile(ctx context.Context, req ctrl.Reques } if updated, err := r.versionAnnotationUpdated(dialer); err == nil && updated { - r.Log.Info("status.secret exists, but the peering doesn't exist in Consul; establishing peering with the existing spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) + r.Log.Info("the version annotation was incremented; re-establishing peering with spec.peer.secret", "secret-name", dialer.Secret().Name, "secret-namespace", dialer.Namespace) peeringToken := specSecret.Data[dialer.Secret().Key] if err := r.establishPeering(ctx, dialer.Name, string(peeringToken)); err != nil { r.updateStatusError(ctx, dialer, ConsulAgentError, err) diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index 24471a26dc..39f0a8344f 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -2,11 +2,7 @@ package connectinject import ( "context" - "encoding/base64" - "encoding/json" "errors" - "fmt" - "strings" "testing" "time" @@ -270,34 +266,22 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { // Create fake k8s client k8sObjects := append(tt.k8sObjects(), &ns) - // This is responsible for updating the token generated by the acceptor side with the IP - // of the Consul server as the generated token currently does not have that set on it. + // Generate a token. var encodedPeeringToken string if tt.peeringName != "" { - var token struct { - CA string - ServerAddresses []string - ServerName string - PeerID string - } // Create the initial token. baseToken, _, err := acceptorClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: tt.peeringName}, nil) require.NoError(t, err) - // Decode the token to extract the ServerName and PeerID from the token. CA is always NULL. - decodeBytes, err := base64.StdEncoding.DecodeString(baseToken.PeeringToken) - require.NoError(t, err) - err = json.Unmarshal(decodeBytes, &token) - require.NoError(t, err) - // Get the IP of the Consul server. - addr := strings.Split(acceptorPeerServer.HTTPAddr, ":")[0] - port := strings.Split(acceptorPeerServer.GRPCAddr, ":")[1] - // Generate expected token for Peering Initiate. - tokenString := fmt.Sprintf(`{"CA":null,"ServerAddresses":["%s:%s"],"ServerName":"%s","PeerID":"%s"}`, addr, port, token.ServerName, token.PeerID) - // Create peering initiate secret in Kubernetes. - encodedPeeringToken = base64.StdEncoding.EncodeToString([]byte(tokenString)) + encodedPeeringToken = baseToken.PeeringToken + } + + // If the peering is not supposed to already exist in Consul, then create a secret with the generated token. + if !tt.peeringExists { secret := tt.peeringSecret(encodedPeeringToken) - secret.SetResourceVersion("latest-version") - k8sObjects = append(k8sObjects, secret) + if secret != nil { + secret.SetResourceVersion("latest-version") + k8sObjects = append(k8sObjects, secret) + } } // Create test consul server. @@ -314,12 +298,19 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { dialerClient, err := api.NewClient(cfg) require.NoError(t, err) + // If the peering is supposed to already exist in Consul, then establish a peering with the existing token, so the peering will exist on the dialing side. if tt.peeringExists { _, _, err := dialerClient.Peerings().Establish(context.Background(), api.PeeringEstablishRequest{PeerName: tt.peeringName, PeeringToken: encodedPeeringToken}, nil) require.NoError(t, err) k8sObjects = append(k8sObjects, createSecret("dialer-token-old", "default", "token", "old-token")) + // Create a new token to be used by Reconcile(). The original token has already been + // used once to simulate establishing an existing peering. + baseToken, _, err := acceptorClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: tt.peeringName}, nil) + require.NoError(t, err) + secret := tt.peeringSecret(baseToken.PeeringToken) + secret.SetResourceVersion("latest-version") + k8sObjects = append(k8sObjects, secret) } - s := scheme.Scheme s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringDialer{}, &v1alpha1.PeeringDialerList{}) fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(k8sObjects...).Build() @@ -481,32 +472,11 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { // Create fake k8s client k8sObjects := []runtime.Object{dialer, ns} - // This is responsible for updating the token generated by the acceptor side with the IP - // of the Consul server as the generated token currently does not have that set on it. - var encodedPeeringToken string - var token struct { - CA string - ServerAddresses []string - ServerName string - PeerID string - } - // Create the initial token. - baseToken, _, err := acceptorClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: "peering"}, nil) + // Create a peering connection in Consul by generating and establishing a peering connection before calling + // Reconcile(). + // Generate a token. + generatedToken, _, err := acceptorClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: "peering"}, nil) require.NoError(t, err) - // Decode the token to extract the ServerName and PeerID from the token. CA is always NULL. - decodeBytes, err := base64.StdEncoding.DecodeString(baseToken.PeeringToken) - require.NoError(t, err) - err = json.Unmarshal(decodeBytes, &token) - require.NoError(t, err) - // Get the IP of the Consul server. - addr := strings.Split(acceptorPeerServer.HTTPAddr, ":")[0] - // Generate expected token for Peering Initiate. - tokenString := fmt.Sprintf(`{"CA":null,"ServerAddresses":["%s:8300"],"ServerName":"%s","PeerID":"%s"}`, addr, token.ServerName, token.PeerID) - // Create peering initiate secret in Kubernetes. - encodedPeeringToken = base64.StdEncoding.EncodeToString([]byte(tokenString)) - secret := createSecret("dialer-token", "default", "token", encodedPeeringToken) - secret.SetResourceVersion("latest-version") - k8sObjects = append(k8sObjects, secret) // Create test consul server. dialerPeerServer, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) { @@ -522,10 +492,19 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { dialerClient, err := api.NewClient(cfg) require.NoError(t, err) - _, _, err = dialerClient.Peerings().Establish(context.Background(), api.PeeringEstablishRequest{PeerName: "peering", PeeringToken: encodedPeeringToken}, nil) + // Establish a peering with the generated token. + _, _, err = dialerClient.Peerings().Establish(context.Background(), api.PeeringEstablishRequest{PeerName: "peering", PeeringToken: generatedToken.PeeringToken}, nil) require.NoError(t, err) k8sObjects = append(k8sObjects, createSecret("dialer-token-old", "default", "token", "old-token")) + // Create a new token to be potentially used by Reconcile(). The original token has already been + // used once to simulate establishing an existing peering. + token, _, err := acceptorClient.Peerings().GenerateToken(context.Background(), api.PeeringGenerateTokenRequest{PeerName: "peering"}, nil) + require.NoError(t, err) + secret := createSecret("dialer-token", "default", "token", token.PeeringToken) + secret.SetResourceVersion("latest-version") + k8sObjects = append(k8sObjects, secret) + s := scheme.Scheme s.AddKnownTypes(v1alpha1.GroupVersion, &v1alpha1.PeeringDialer{}, &v1alpha1.PeeringDialerList{}) fakeClient := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(k8sObjects...).Build() From 957f4e41cce3e60ecc96bcc95d8169dba2f057b3 Mon Sep 17 00:00:00 2001 From: Erik Berg Date: Wed, 10 Aug 2022 22:59:45 +0200 Subject: [PATCH 073/235] fix permissions for /consul/extra-config (#1307) * fix permissions for /consul/extra-config in openshift environments On openshift/okd you might not have permissions to create directories everywhere. But you can introduce mounts. Here we're just creating insignificant mount-points for the extra-config to do it's thing, thus eliminating the need for creating the directory, which the user running the container might not have permissions to do. Fixes #1306 --- charts/consul/templates/_helpers.tpl | 1 - charts/consul/templates/client-daemonset.yaml | 4 ++ .../consul/templates/server-statefulset.yaml | 4 ++ charts/consul/test/unit/client-daemonset.bats | 69 +++++++++++-------- .../consul/test/unit/server-statefulset.bats | 25 ++++++- 5 files changed, 71 insertions(+), 32 deletions(-) diff --git a/charts/consul/templates/_helpers.tpl b/charts/consul/templates/_helpers.tpl index b667bdb460..fceb75ce5a 100644 --- a/charts/consul/templates/_helpers.tpl +++ b/charts/consul/templates/_helpers.tpl @@ -142,7 +142,6 @@ substitution for HOST_IP/POD_IP/HOSTNAME. Useful for dogstats telemetry. The out is passed to consul as a -config-file param on command line. */}} {{- define "consul.extraconfig" -}} - mkdir -p /consul/extra-config cp /consul/config/extra-from-values.json /consul/extra-config/extra-from-values.json [ -n "${HOST_IP}" ] && sed -Ei "s|HOST_IP|${HOST_IP?}|g" /consul/extra-config/extra-from-values.json [ -n "${POD_IP}" ] && sed -Ei "s|POD_IP|${POD_IP?}|g" /consul/extra-config/extra-from-values.json diff --git a/charts/consul/templates/client-daemonset.yaml b/charts/consul/templates/client-daemonset.yaml index 83f410fd0c..1a51d69b90 100644 --- a/charts/consul/templates/client-daemonset.yaml +++ b/charts/consul/templates/client-daemonset.yaml @@ -125,6 +125,8 @@ spec: - name: config configMap: name: {{ template "consul.fullname" . }}-client-config + - name: extra-config + emptyDir: {} - name: consul-data emptyDir: medium: "Memory" @@ -384,6 +386,8 @@ spec: mountPath: /consul/data - name: config mountPath: /consul/config + - name: extra-config + mountPath: /consul/extra-config - mountPath: /consul/login name: consul-data readOnly: true diff --git a/charts/consul/templates/server-statefulset.yaml b/charts/consul/templates/server-statefulset.yaml index 42df4f2f58..71b424cc68 100644 --- a/charts/consul/templates/server-statefulset.yaml +++ b/charts/consul/templates/server-statefulset.yaml @@ -129,6 +129,8 @@ spec: - name: config configMap: name: {{ template "consul.fullname" . }}-server-config + - name: extra-config + emptyDir: {} {{- if (and .Values.global.tls.enabled (not .Values.global.secretsBackend.vault.enabled)) }} - name: consul-ca-cert secret: @@ -302,6 +304,8 @@ spec: mountPath: /consul/data - name: config mountPath: /consul/config + - name: extra-config + mountPath: /consul/extra-config {{- if (and .Values.global.tls.enabled (not .Values.global.secretsBackend.vault.enabled)) }} - name: consul-ca-cert mountPath: /consul/tls/ca/ diff --git a/charts/consul/test/unit/client-daemonset.bats b/charts/consul/test/unit/client-daemonset.bats index b4f1a46d96..24cc4324f2 100755 --- a/charts/consul/test/unit/client-daemonset.bats +++ b/charts/consul/test/unit/client-daemonset.bats @@ -238,6 +238,27 @@ load _helpers [ "${actual}" = "bar" ] } +#-------------------------------------------------------------------- +# extra-config + +@test "client/DaemonSet: has extra-config volume" { + cd `chart_dir` + + # check that the extra-config volume is defined + local volume_name=$(helm template \ + -s templates/client-daemonset.yaml \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.volumes[] | select(.name == "extra-config") | .name' | tee /dev/stderr) + [ "${volume_name}" = "extra-config" ] + + # check that the consul container mounts the volume at /consul/extra-config + local mount_path=$(helm template \ + -s templates/client-daemonset.yaml \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[] | select(.name == "consul") | .volumeMounts[] | select(.name == "extra-config") | .mountPath' | tee /dev/stderr) + [ "${mount_path}" = "/consul/extra-config" ] +} + #-------------------------------------------------------------------- # extraVolumes @@ -1100,29 +1121,22 @@ load _helpers @test "client/DaemonSet: aclconfig volume is created when global.acls.manageSystemACLs=true" { cd `chart_dir` - local actual=$(helm template \ + local volume_name=$(helm template \ -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq '.spec.template.spec.volumes[3].name == "aclconfig"' | tee /dev/stderr) - [ "${actual}" = "true" ] + yq -r '.spec.template.spec.volumes[] | select(.name == "aclconfig") | .name' | tee /dev/stderr) + [ "${volume_name}" = "aclconfig" ] } @test "client/DaemonSet: aclconfig volumeMount is created when global.acls.manageSystemACLs=true" { cd `chart_dir` - local object=$(helm template \ + local mount_path=$(helm template \ -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq '.spec.template.spec.containers[0].volumeMounts[3]' | tee /dev/stderr) - - local actual=$(echo $object | - yq -r '.name' | tee /dev/stderr) - [ "${actual}" = "aclconfig" ] - - local actual=$(echo $object | - yq -r '.mountPath' | tee /dev/stderr) - [ "${actual}" = "/consul/aclconfig" ] + yq -r '.spec.template.spec.containers[] | select(.name == "consul") | .volumeMounts[] | select(.name == "aclconfig") | .mountPath' | tee /dev/stderr) + [ "${mount_path}" = "/consul/aclconfig" ] } @test "client/DaemonSet: command includes aclconfig dir when global.acls.manageSystemACLs=true" { @@ -1260,37 +1274,34 @@ local actual=$(echo $object | @test "client/DaemonSet: Adds consul login volume when ACLs are enabled" { cd `chart_dir` - local object=$(helm template \ + local volume=$(helm template \ -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ - . | yq '.spec.template.spec.volumes[2]' | tee /dev/stderr) - local actual=$(echo $object | + . | yq '.spec.template.spec.volumes[] | select(.name == "consul-data")' | tee /dev/stderr) + + local volume_name=$(echo $volume | yq -r '.name' | tee /dev/stderr) - [ "${actual}" = "consul-data" ] + [ "${volume_name}" = "consul-data" ] - local actual=$(echo $object | + local volume_emptydir_medium=$(echo $volume | yq -r '.emptyDir.medium' | tee /dev/stderr) - [ "${actual}" = "Memory" ] + [ "${volume_emptydir_medium}" = "Memory" ] } @test "client/DaemonSet: Adds consul login volumeMount to client container when ACLs are enabled" { cd `chart_dir` - local object=$(helm template \ + local volume_mount=$(helm template \ -s templates/client-daemonset.yaml \ --set 'global.acls.manageSystemACLs=true' \ - . | yq '.spec.template.spec.containers[0].volumeMounts[2]' | tee /dev/stderr) + . | yq '.spec.template.spec.containers[] | select(.name == "consul") | .volumeMounts[] | select(.name == "consul-data")' | tee /dev/stderr) - local actual=$(echo $object | - yq -r '.name' | tee /dev/stderr) - [ "${actual}" = "consul-data" ] - - local actual=$(echo $object | + local volume_mount_path=$(echo $volume_mount | yq -r '.mountPath' | tee /dev/stderr) - [ "${actual}" = "/consul/login" ] + [ "${volume_mount_path}" = "/consul/login" ] - local actual=$(echo $object | + local volume_mount_ro=$(echo $volume_mount | yq -r '.readOnly' | tee /dev/stderr) - [ "${actual}" = "true" ] + [ "${volume_mount_ro}" = "true" ] } @test "client/DaemonSet: Adds consul login volumeMount to acl-init init container when ACLs are enabled" { diff --git a/charts/consul/test/unit/server-statefulset.bats b/charts/consul/test/unit/server-statefulset.bats index 3063a0e905..a725162e01 100755 --- a/charts/consul/test/unit/server-statefulset.bats +++ b/charts/consul/test/unit/server-statefulset.bats @@ -207,7 +207,7 @@ load _helpers . | tee /dev/stderr ) local actual=$(echo "$object" | - yq -r '.spec.template.spec.volumes[2].secret.secretName' | tee /dev/stderr) + yq -r '.spec.template.spec.volumes[] | select(.name == "consul-server-cert") | .secret.secretName' | tee /dev/stderr) [ "${actual}" = "release-name-consul-server-cert" ] } @@ -221,7 +221,7 @@ load _helpers . | tee /dev/stderr ) local actual=$(echo "$object" | - yq -r '.spec.template.spec.volumes[2].secret.secretName' | tee /dev/stderr) + yq -r '.spec.template.spec.volumes[] | select(.name == "consul-server-cert") | .secret.secretName' | tee /dev/stderr) [ "${actual}" = "server-cert" ] } @@ -348,6 +348,27 @@ load _helpers yq -r '.spec.template.spec.containers[0].command' | tee /dev/stderr) } +#-------------------------------------------------------------------- +# extra-config + +@test "server/StatefulSet: has extra-config volume" { + cd `chart_dir` + + # check that the extra-config volume is defined + local volume_name=$(helm template \ + -s templates/server-statefulset.yaml \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.volumes[] | select(.name == "extra-config") | .name' | tee /dev/stderr) + [ "${volume_name}" = "extra-config" ] + + # check that the consul container mounts the volume at /consul/extra-config + local mount_path=$(helm template \ + -s templates/server-statefulset.yaml \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[] | select(.name == "consul") | .volumeMounts[] | select(.name == "extra-config") | .mountPath' | tee /dev/stderr) + [ "${mount_path}" = "/consul/extra-config" ] +} + #-------------------------------------------------------------------- # extraVolumes From 21a3710f445951060357211656f2b2842ea94e80 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Wed, 10 Aug 2022 19:41:02 -0400 Subject: [PATCH 074/235] Fix issue where API gateways were being mis-labeled as Sidecar proxies (#1403) --- cli/cmd/proxy/list/command.go | 12 ++++++++++-- cli/cmd/proxy/list/command_test.go | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cli/cmd/proxy/list/command.go b/cli/cmd/proxy/list/command.go index 4389eec0db..cc09278861 100644 --- a/cli/cmd/proxy/list/command.go +++ b/cli/cmd/proxy/list/command.go @@ -204,6 +204,8 @@ func (c *ListCommand) output(pods []v1.Pod) { for _, pod := range pods { var proxyType string + + // Get the type for ingress, mesh, and terminating gateways. switch pod.Labels["component"] { case "ingress-gateway": proxyType = "Ingress Gateway" @@ -211,9 +213,15 @@ func (c *ListCommand) output(pods []v1.Pod) { proxyType = "Mesh Gateway" case "terminating-gateway": proxyType = "Terminating Gateway" - case "api-gateway": + } + + // Determine if the pod is an API Gateway. + if pod.Labels["api-gateway.consul.hashicorp.com/managed"] == "true" { proxyType = "API Gateway" - default: + } + + // Fallback to "Sidecar" as a default + if proxyType == "" { proxyType = "Sidecar" } diff --git a/cli/cmd/proxy/list/command_test.go b/cli/cmd/proxy/list/command_test.go index f0d552ca7f..df6aaf024b 100644 --- a/cli/cmd/proxy/list/command_test.go +++ b/cli/cmd/proxy/list/command_test.go @@ -225,7 +225,7 @@ func TestListCommandOutput(t *testing.T) { "consul.*mesh-gateway.*Mesh Gateway", "consul.*terminating-gateway.*Terminating Gateway", "default.*ingress-gateway.*Ingress Gateway", - "consul.*api-gateway.*Sidecar", + "consul.*api-gateway.*API Gateway", "default.*pod1.*Sidecar", } notExpected := []string{ From e403f354bc7610dcc64cfd7a3baddef28ee2a730 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Wed, 10 Aug 2022 18:46:17 -0500 Subject: [PATCH 075/235] update changelog (#1405) * Update CHANGELOG.md Co-authored-by: Iryna Shustava --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07fab92f01..0c922b3d7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,10 @@ IMPROVEMENTS: * Bump default Envoy version to 1.23.0. [[GH-1377](https://github.com/hashicorp/consul-k8s/pull/1377)] * Added support for Consul API Gateway to read ReferenceGrant custom resources. This will require either installing Consul API Gateway CRDs from the upcoming v0.4.0 release with `kubectl apply --kustomize "github.com/hashicorp/consul-api-gateway/config/crd?ref=v0.4.0"` or manually installing the ReferenceGrant CRD from the Gateway API v0.5 [Experimental Channel](https://gateway-api.sigs.k8s.io/concepts/versioning/#release-channels-eg-experimental-standard) when setting `apiGateway.enabled=true` [[GH-1299](https://github.com/hashicorp/consul-k8s/pull/1299)] +BUG FIXES: +* Helm + * Fix permissions in client-daemonset and server-statefulset when using extra-config volumes to prevent errors on openshift. [[GH-1307](https://github.com/hashicorp/consul-k8s/pull/1307)] + ## 0.46.1 (July 26, 2022) IMPROVEMENTS: From f8331dab37de8e29e46b752daa305388deebc4a5 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Thu, 11 Aug 2022 09:38:08 -0400 Subject: [PATCH 076/235] Fix context handling for the CLI (#1406) * Use context as set by user for Kubernetes * Pass in context using Kube options to CLI run commands --- acceptance/framework/cli/cli.go | 16 +++++++++++++++- acceptance/framework/consul/cli_cluster.go | 8 +++----- acceptance/tests/connect/connect_inject_test.go | 4 ++-- cli/cmd/proxy/list/command.go | 8 ++++++++ cli/cmd/proxy/read/command.go | 4 ++-- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/acceptance/framework/cli/cli.go b/acceptance/framework/cli/cli.go index 012ac349a5..11f55ade1d 100644 --- a/acceptance/framework/cli/cli.go +++ b/acceptance/framework/cli/cli.go @@ -3,8 +3,12 @@ package cli import ( "fmt" "os/exec" + "strings" + "testing" + "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/config" + "github.com/hashicorp/consul-k8s/acceptance/framework/logger" ) // CLI provides access to compile and execute commands with the `consul-k8s` CLI. @@ -22,10 +26,20 @@ func NewCLI() (*CLI, error) { } // Run runs the CLI with the given args. -func (c *CLI) Run(args ...string) ([]byte, error) { +func (c *CLI) Run(t *testing.T, options *k8s.KubectlOptions, args ...string) ([]byte, error) { if !c.initialized { return nil, fmt.Errorf("CLI must be initialized before calling Run, use `cli.NewCLI()` to initialize.") } + + // Append configuration from `options` to the command. + if options.ConfigPath != "" { + args = append(args, "-config", options.ConfigPath) + } + if options.ContextName != "" { + args = append(args, "-context", options.ContextName) + } + + logger.Logf(t, "Running `consul-k8s %s`", strings.Join(args, " ")) cmd := exec.Command("cli", args...) return cmd.Output() } diff --git a/acceptance/framework/consul/cli_cluster.go b/acceptance/framework/consul/cli_cluster.go index cf7f1851de..271f8f2eae 100644 --- a/acceptance/framework/consul/cli_cluster.go +++ b/acceptance/framework/consul/cli_cluster.go @@ -124,7 +124,6 @@ func (c *CLICluster) Create(t *testing.T) { // Set the args for running the install command. args := []string{"install"} - args = c.setKube(args) for k, v := range c.values { args = append(args, "-set", fmt.Sprintf("%s=%s", k, v)) @@ -134,7 +133,7 @@ func (c *CLICluster) Create(t *testing.T) { args = append(args, "-timeout", "15m") args = append(args, "-auto-approve") - out, err := c.cli.Run(args...) + out, err := c.cli.Run(t, c.kubectlOptions, args...) if err != nil { c.logger.Logf(t, "error running command `consul-k8s %s`: %s", strings.Join(args, " "), err.Error()) c.logger.Logf(t, "command stdout: %s", string(out)) @@ -167,7 +166,7 @@ func (c *CLICluster) Upgrade(t *testing.T, helmValues map[string]string) { args = append(args, "-timeout", "15m") args = append(args, "-auto-approve") - out, err := c.cli.Run(args...) + out, err := c.cli.Run(t, c.kubectlOptions, args...) if err != nil { c.logger.Logf(t, "error running command `consul-k8s %s`: %s", strings.Join(args, " "), err.Error()) c.logger.Logf(t, "command stdout: %s", string(out)) @@ -185,13 +184,12 @@ func (c *CLICluster) Destroy(t *testing.T) { // Set the args for running the uninstall command. args := []string{"uninstall"} - args = c.setKube(args) args = append(args, "-auto-approve", "-wipe-data") // Use `go run` so that the CLI is recompiled and therefore uses the local // charts directory rather than the directory from whenever it was last // compiled. - out, err := c.cli.Run(args...) + out, err := c.cli.Run(t, c.kubectlOptions, args...) if err != nil { c.logger.Logf(t, "error running command `consul-k8s %s`: %s", strings.Join(args, " "), err.Error()) c.logger.Logf(t, "command stdout: %s", string(out)) diff --git a/acceptance/tests/connect/connect_inject_test.go b/acceptance/tests/connect/connect_inject_test.go index 5cba67f045..b57e188fdb 100644 --- a/acceptance/tests/connect/connect_inject_test.go +++ b/acceptance/tests/connect/connect_inject_test.go @@ -88,7 +88,7 @@ func TestConnectInject(t *testing.T) { } // Run proxy list and get the two results. - listOut, err := cli.Run("proxy", "list") + listOut, err := cli.Run(t, ctx.KubectlOptions(t), "proxy", "list") require.NoError(t, err) logger.Log(t, string(listOut)) list := translateListOutput(listOut) @@ -101,7 +101,7 @@ func TestConnectInject(t *testing.T) { retrier := &retry.Timer{Timeout: 160 * time.Second, Wait: 2 * time.Second} retry.RunWith(retrier, t, func(r *retry.R) { for podName := range list { - out, err := cli.Run("proxy", "read", podName) + out, err := cli.Run(t, ctx.KubectlOptions(t), "proxy", "read", podName) require.NoError(t, err) output := string(out) diff --git a/cli/cmd/proxy/list/command.go b/cli/cmd/proxy/list/command.go index cc09278861..9d62351857 100644 --- a/cli/cmd/proxy/list/command.go +++ b/cli/cmd/proxy/list/command.go @@ -134,6 +134,14 @@ func (c *ListCommand) validateFlags() error { func (c *ListCommand) initKubernetes() error { settings := helmCLI.New() + if c.flagKubeConfig != "" { + settings.KubeConfig = c.flagKubeConfig + } + + if c.flagKubeContext != "" { + settings.KubeContext = c.flagKubeContext + } + restConfig, err := settings.RESTClientGetter().ToRESTConfig() if err != nil { return fmt.Errorf("error retrieving Kubernetes authentication %v", err) diff --git a/cli/cmd/proxy/read/command.go b/cli/cmd/proxy/read/command.go index 227adbfee9..31e1d20892 100644 --- a/cli/cmd/proxy/read/command.go +++ b/cli/cmd/proxy/read/command.go @@ -229,11 +229,11 @@ func (c *ReadCommand) validateFlags() error { func (c *ReadCommand) initKubernetes() (err error) { settings := helmCLI.New() - if c.flagKubeConfig == "" { + if c.flagKubeConfig != "" { settings.KubeConfig = c.flagKubeConfig } - if c.flagKubeContext == "" { + if c.flagKubeContext != "" { settings.KubeContext = c.flagKubeContext } From e47b00630f568771f6113798b46699f09ace7469 Mon Sep 17 00:00:00 2001 From: David Yu Date: Thu, 11 Aug 2022 08:42:22 -0700 Subject: [PATCH 077/235] CHANGELOG: small formatting fixes (#1407) * CHANGELOG: small formatting fixes --- CHANGELOG.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c922b3d7f..a87483625a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ FEATURES: * Transparent Proxy Egress * Add support for Destinations on the Service Defaults CRD. [[GH-1352](https://github.com/hashicorp/consul-k8s/pull/1352)] * CLI: - * Add `consul-k8s proxy list` command for displaying Pods running Envoy managed by Consul. [[GH-1271](https://github.com/hashicorp/consul-k8s/pull/1271) - * Add `consul-k8s proxy read podname` command for displaying Envoy configuration for a given Pod. [[GH-1271](https://github.com/hashicorp/consul-k8s/pull/1271) + * Add `consul-k8s proxy list` command for displaying Pods running Envoy managed by Consul. [[GH-1271](https://github.com/hashicorp/consul-k8s/pull/1271)] + * Add `consul-k8s proxy read podname` command for displaying Envoy configuration for a given Pod. [[GH-1271](https://github.com/hashicorp/consul-k8s/pull/1271)] * [Experimental] Cluster Peering: * Add support for ACLs and TLS. [[GH-1343](https://github.com/hashicorp/consul-k8s/pull/1343)] [[GH-1366](https://github.com/hashicorp/consul-k8s/pull/1366)] * Add support for Load Balancers or external addresses in front of Consul servers for peering stream. @@ -21,7 +21,7 @@ IMPROVEMENTS: BUG FIXES: * Helm - * Fix permissions in client-daemonset and server-statefulset when using extra-config volumes to prevent errors on openshift. [[GH-1307](https://github.com/hashicorp/consul-k8s/pull/1307)] + * Fix permissions in client-daemonset and server-statefulset when using extra-config volumes to prevent errors on OpenShift. [[GH-1307](https://github.com/hashicorp/consul-k8s/pull/1307)] ## 0.46.1 (July 26, 2022) @@ -30,11 +30,6 @@ IMPROVEMENTS: * Update alpine to 3.16 in the Docker image. [[GH-1372](https://github.com/hashicorp/consul-k8s/pull/1372)] ## 0.46.0 (July 20, 2022) -IMPROVEMENTS: -* Control Plane - * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] -* CLI - * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] FEATURES: * [Experimental] Cluster Peering: @@ -47,9 +42,12 @@ IMPROVEMENTS: * Control Plane * Added annotations `consul.hashicorp.com/prometheus-ca-file`, `consul.hashicorp.com/prometheus-ca-path`, `consul.hashicorp.com/prometheus-cert-file`, and `consul.hashicorp.com/prometheus-key-file` for configuring TLS scraping on Prometheus metrics endpoints for Envoy sidecars. To enable, set the cert and key file annotations along with one of the ca file/path annotations. [[GH-1303](https://github.com/hashicorp/consul-k8s/pull/1303)] * Added annotations `consul.hashicorp.com/consul-sidecar-user-volume` and `consul.hashicorp.com/consul-sidecar-user-volume-mount` for attaching Volumes and VolumeMounts to the Envoy sidecar. Both should be JSON objects. [[GH-1315](https://github.com/hashicorp/consul-k8s/pull/1315)] + * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] * Helm * Added `connectInject.annotations` and `syncCatalog.annotations` values for setting annotations on connect inject and sync catalog deployments. [[GH-775](https://github.com/hashicorp/consul-k8s/pull/775)] * Added PodDisruptionBudget to the connect injector deployment which can be configured using the `connectInject.disruptionBudget` stanza. [[GH-1316](https://github.com/hashicorp/consul-k8s/pull/1316)] +* CLI + * Update minimum go version for project to 1.18 [[GH-1292](https://github.com/hashicorp/consul-k8s/pull/1292)] BUG FIXES: * Helm From 12cb347276adc167c5600eaa50ca87c33d3c2b28 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Fri, 12 Aug 2022 06:58:01 -0600 Subject: [PATCH 078/235] Release 0.47.0 (#1413) * add changelog * Update consul version in ci and api/sdk package versions * update release date --- .circleci/config.yml | 2 -- .github/workflows/test.yml | 4 ++-- CHANGELOG.md | 4 ++-- acceptance/go.mod | 4 ++-- acceptance/go.sum | 4 ++++ charts/consul/Chart.yaml | 10 +++++----- charts/consul/values.yaml | 4 ++-- cli/version/version.go | 4 ++-- control-plane/go.mod | 4 ++-- control-plane/go.sum | 4 ++++ control-plane/version/version.go | 4 ++-- 11 files changed, 27 insertions(+), 21 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9fd989b7e8..88649ec789 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -101,7 +101,6 @@ commands: ${ENABLE_ENTERPRISE:+-enable-enterprise} \ -enable-multi-cluster \ -debug-directory="$TEST_RESULTS/debug" \ - -consul-image=docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev \ -consul-k8s-image=<< parameters.consul-k8s-image >> then echo "Tests in ${pkg} failed, aborting early" @@ -133,7 +132,6 @@ commands: -enable-multi-cluster \ ${ENABLE_ENTERPRISE:+-enable-enterprise} \ -debug-directory="$TEST_RESULTS/debug" \ - -consul-image=docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev \ -consul-k8s-image=<< parameters.consul-k8s-image >> jobs: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6b90795000..4d651e8769 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,8 +4,8 @@ on: env: TEST_RESULTS: /tmp/test-results # path to where test results are saved - CONSUL_VERSION: 1.13.0 # Consul's OSS version to use in tests - CONSUL_ENT_VERSION: 1.13.0+ent # Consul's enterprise version to use in tests + CONSUL_VERSION: 1.13.1 # Consul's OSS version to use in tests + CONSUL_ENT_VERSION: 1.13.1+ent # Consul's enterprise version to use in tests GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. jobs: diff --git a/CHANGELOG.md b/CHANGELOG.md index a87483625a..5aeee07cf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.47.0 (August 12, 2022) FEATURES: * Transparent Proxy Egress @@ -16,7 +16,7 @@ FEATURES: IMPROVEMENTS: * Helm - * Bump default Envoy version to 1.23.0. [[GH-1377](https://github.com/hashicorp/consul-k8s/pull/1377)] + * Bump default Envoy version to 1.22.4. [[GH-1413](https://github.com/hashicorp/consul-k8s/pull/1413)] * Added support for Consul API Gateway to read ReferenceGrant custom resources. This will require either installing Consul API Gateway CRDs from the upcoming v0.4.0 release with `kubectl apply --kustomize "github.com/hashicorp/consul-api-gateway/config/crd?ref=v0.4.0"` or manually installing the ReferenceGrant CRD from the Gateway API v0.5 [Experimental Channel](https://gateway-api.sigs.k8s.io/concepts/versioning/#release-channels-eg-experimental-standard) when setting `apiGateway.enabled=true` [[GH-1299](https://github.com/hashicorp/consul-k8s/pull/1299)] BUG FIXES: diff --git a/acceptance/go.mod b/acceptance/go.mod index 1115a3a7a5..b7b11bc27c 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -5,8 +5,8 @@ go 1.18 require ( github.com/gruntwork-io/terratest v0.31.2 github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638 - github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df - github.com/hashicorp/consul/sdk v0.10.0 + github.com/hashicorp/consul/api v1.14.0 + github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.2.0 github.com/hashicorp/vault/api v1.2.0 diff --git a/acceptance/go.sum b/acceptance/go.sum index f430da635a..c4e8c9b20e 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -326,8 +326,12 @@ github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638 github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638/go.mod h1:7ZeaiADGbvJDuoWAT8UKj6KCcLsFUk+34OkUGMVtdXg= github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df h1:CCh336XUGPaMNqMkzRAeEL0BFin7LhX729xy3IxE5Y4= github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk= +github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI= github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= +github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index faede92331..fd91208f9e 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul -version: 0.46.1 -appVersion: 1.12.3 +version: 0.47.0 +appVersion: 1.13.1 kubeVersion: ">=1.19.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -13,11 +13,11 @@ annotations: artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.12.3 + image: hashicorp/consul:1.13.1 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.46.1 + image: hashicorp/consul-k8s-control-plane:0.47.0 - name: envoy - image: envoyproxy/envoy:v1.23.0 + image: envoyproxy/envoy:v1.22.4 artifacthub.io/license: MPL-2.0 artifacthub.io/links: | - name: Documentation diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index b0f7508e9c..737fd8c124 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -107,7 +107,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.12.3" + image: "hashicorp/consul:1.13.1" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -627,7 +627,7 @@ global: # connect-injected sidecar proxies and mesh, terminating, and ingress gateways. # See https://www.consul.io/docs/connect/proxies/envoy for full compatibility matrix between Consul and Envoy. # @default: envoyproxy/envoy-alpine: - imageEnvoy: "envoyproxy/envoy:v1.23.0" + imageEnvoy: "envoyproxy/envoy:v1.22.4" # Configuration for running this Helm chart on the Red Hat OpenShift platform. # This Helm chart currently supports OpenShift v4.x+. diff --git a/cli/version/version.go b/cli/version/version.go index ce4f269c93..f7b18c28b0 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.46.1" + Version = "0.47.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/go.mod b/control-plane/go.mod index b7ad080d00..20e4a034ca 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -6,8 +6,8 @@ require ( github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c - github.com/hashicorp/consul/sdk v0.10.0 + github.com/hashicorp/consul/api v1.14.0 + github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f github.com/hashicorp/go-hclog v0.16.1 github.com/hashicorp/go-multierror v1.1.1 diff --git a/control-plane/go.sum b/control-plane/go.sum index 5d041e633a..15fd29f9a8 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -298,9 +298,13 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c h1:lEMAoMGwTncIh9opSHvvGxM0WrNT5YuCbKipwtU7UNs= github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk= +github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51 h1:jLjJ0p6QaJFg0PJjWcx+qWTTMujanlJRIRJl15jvG8I= github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= +github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= diff --git a/control-plane/version/version.go b/control-plane/version/version.go index ce4f269c93..f7b18c28b0 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.46.1" + Version = "0.47.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 97b26155cb58660671cf6feaf91dfde248a51f46 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Fri, 12 Aug 2022 08:28:44 -0700 Subject: [PATCH 079/235] peering: update helm value doc (#1415) --- charts/consul/values.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 737fd8c124..3692937571 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -39,7 +39,9 @@ global: # Source can be set to "","consul" or "static". # # "" is the default source. If servers are enabled, it will check if `server.exposeService` is enabled, and read - # the addresses from that service to use as the peering token server addresses. + # the addresses from that service to use as the peering token server addresses. If using admin partitions and + # only Consul client agents are enabled, the addresses in externalServers.hosts and externalServers.grpcPort + # will be used. # # "consul" will use the Consul advertise addresses in the peering token. # From a296bd057b45527ad0eade96305c09281b348a6f Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 12 Aug 2022 12:49:03 -0400 Subject: [PATCH 080/235] revert to dev mode (#1416) --- CHANGELOG.md | 2 ++ cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5aeee07cf6..2e042d191b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.47.0 (August 12, 2022) FEATURES: diff --git a/cli/version/version.go b/cli/version/version.go index f7b18c28b0..4e22c2ca40 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index f7b18c28b0..4e22c2ca40 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 8029b4f1b502a4b66e802ed9fe37de9aa8b46432 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 12 Aug 2022 13:40:24 -0400 Subject: [PATCH 081/235] 0.47.1 (#1417) --- charts/consul/Chart.yaml | 4 ++-- charts/consul/values.yaml | 2 +- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index fd91208f9e..65fe2d2825 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.47.0 +version: 0.47.1 appVersion: 1.13.1 kubeVersion: ">=1.19.0-0" description: Official HashiCorp Consul Chart @@ -15,7 +15,7 @@ annotations: - name: consul image: hashicorp/consul:1.13.1 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.47.0 + image: hashicorp/consul-k8s-control-plane:0.47.1 - name: envoy image: envoyproxy/envoy:v1.22.4 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 3692937571..6c5dd4dced 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.46.0 + imageK8S: hashicorp/consul-k8s-control-plane:0.47.1 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 4e22c2ca40..9106f59bc7 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,7 +14,7 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.47.0" + Version = "0.47.1" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 4e22c2ca40..9106f59bc7 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,7 +14,7 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.47.0" + Version = "0.47.1" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release From b16a8a49954d13e7f3e1b959eb55b44f0567acc1 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 12 Aug 2022 13:54:11 -0400 Subject: [PATCH 082/235] 0.47.1 (#1418) --- CHANGELOG.md | 6 +++++- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e042d191b..bb7319afab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ -## UNRELEASED +## 0.47.1 (August 12, 2022) + +BUG FIXES: +* Helm + * Update the version of the `imageK8S` in `values.yaml` to the latest control-plane image. [[GH-1355](https://github.com/hashicorp/consul-k8s/pull/1352)] ## 0.47.0 (August 12, 2022) diff --git a/cli/version/version.go b/cli/version/version.go index 9106f59bc7..891d73d4fc 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 9106f59bc7..891d73d4fc 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From eae0c24e2f972424d37d45c36d8776ca6d45cb37 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Fri, 12 Aug 2022 11:22:04 -0700 Subject: [PATCH 083/235] peering: add code blocks for helm docs (#1419) --- charts/consul/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 6c5dd4dced..dd38152c80 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -40,7 +40,7 @@ global: # # "" is the default source. If servers are enabled, it will check if `server.exposeService` is enabled, and read # the addresses from that service to use as the peering token server addresses. If using admin partitions and - # only Consul client agents are enabled, the addresses in externalServers.hosts and externalServers.grpcPort + # only Consul client agents are enabled, the addresses in `externalServers.hosts` and `externalServers.grpcPort` # will be used. # # "consul" will use the Consul advertise addresses in the peering token. From c6092c6f89da9ba2787edfa1552f10e2c04509cc Mon Sep 17 00:00:00 2001 From: brian shore Date: Fri, 12 Aug 2022 13:13:34 -0700 Subject: [PATCH 084/235] Add stanza to ci.hcl to trigger helm pipeline (#1398) --- .release/ci.hcl | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.release/ci.hcl b/.release/ci.hcl index 403ed13212..1506406aa4 100644 --- a/.release/ci.hcl +++ b/.release/ci.hcl @@ -251,3 +251,16 @@ event "promote-production-packaging" { on = "always" } } + +event "promote-production-helm" { + depends = ["promote-production-packaging"] + action "promote-production-helm" { + organization = "hashicorp" + repository = "crt-workflows-common" + workflow = "promote-production-helm" + } + + notification { + on = "always" + } +} From b3bc6981b169bced09434e2d28be299aa3e0a9c6 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 12 Aug 2022 16:21:18 -0400 Subject: [PATCH 085/235] put repo in dev mode (#1420) --- CHANGELOG.md | 2 ++ cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bb7319afab..650fa52068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.47.1 (August 12, 2022) BUG FIXES: diff --git a/cli/version/version.go b/cli/version/version.go index 891d73d4fc..9106f59bc7 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 891d73d4fc..9106f59bc7 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From e5d1770fdae6778bd86e9221d6da0aabba0bac85 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Mon, 15 Aug 2022 12:33:11 -0400 Subject: [PATCH 086/235] Update the sed match to replace image (#1422) --- control-plane/build-support/functions/10-util.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/control-plane/build-support/functions/10-util.sh b/control-plane/build-support/functions/10-util.sh index 31c8ce61ae..fac66227c3 100644 --- a/control-plane/build-support/functions/10-util.sh +++ b/control-plane/build-support/functions/10-util.sh @@ -671,7 +671,7 @@ function update_version_helm { fi local image_k8s="hashicorp\/consul-k8s-control-plane:$full_version" - sed_i ${SED_EXT} -e "s/(imageK8S:[[:space:]]*)\"[^\"]*\"/\1${image_k8s}/g" "${vfile}" + sed_i ${SED_EXT} -e "s/(imageK8S:[[:space:]]*hashicorp\/consul-k8s-control-plane:)[^\"]*/\1${full_version}/g" "${vfile}" sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version}/g" "${cfile}" sed_i ${SED_EXT} -e "s/(image:[[:space:]]*hashicorp\/consul-k8s-control-plane:)[^\"]*/\1${full_version}/g" "${cfile}" From e51cb6de5fd35a1148ac9ed3bef2459dc02454eb Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Mon, 15 Aug 2022 13:10:35 -0500 Subject: [PATCH 087/235] Use the pointer pkg instead of BYO functions everywhere (#1423) --- .../connect-inject/container_init.go | 32 +++++------------ .../connect-inject/container_init_test.go | 17 ++++----- control-plane/connect-inject/envoy_sidecar.go | 9 ++--- .../connect-inject/envoy_sidecar_test.go | 35 ++++++++++--------- .../peering_acceptor_controller.go | 3 +- .../peering_acceptor_controller_test.go | 11 +++--- .../peering_dialer_controller.go | 3 +- .../peering_dialer_controller_test.go | 11 +++--- control-plane/go.mod | 2 +- control-plane/go.sum | 2 ++ 10 files changed, 60 insertions(+), 65 deletions(-) diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index 1efcce3cab..a1550b3da7 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -10,6 +10,7 @@ import ( "time" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" ) const ( @@ -117,10 +118,10 @@ func (w *MeshWebhook) initCopyContainer() corev1.Container { if !w.EnableOpenShift { container.SecurityContext = &corev1.SecurityContext{ // Set RunAsUser because the default user for the consul container is root and we want to run non-root. - RunAsUser: pointerToInt64(copyContainerUserAndGroupID), - RunAsGroup: pointerToInt64(copyContainerUserAndGroupID), - RunAsNonRoot: pointerToBool(true), - ReadOnlyRootFilesystem: pointerToBool(true), + RunAsUser: pointer.Int64(copyContainerUserAndGroupID), + RunAsGroup: pointer.Int64(copyContainerUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), } } return container @@ -297,11 +298,11 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, // Running consul connect redirect-traffic with iptables // requires both being a root user and having NET_ADMIN capability. container.SecurityContext = &corev1.SecurityContext{ - RunAsUser: pointerToInt64(rootUserAndGroupID), - RunAsGroup: pointerToInt64(rootUserAndGroupID), + RunAsUser: pointer.Int64(rootUserAndGroupID), + RunAsGroup: pointer.Int64(rootUserAndGroupID), // RunAsNonRoot overrides any setting in the Pod so that we can still run as root here as required. - RunAsNonRoot: pointerToBool(false), - Privileged: pointerToBool(true), + RunAsNonRoot: pointer.Bool(false), + Privileged: pointer.Bool(true), Capabilities: &corev1.Capabilities{ Add: []corev1.Capability{netAdminCapability}, }, @@ -352,21 +353,6 @@ func consulDNSEnabled(namespace corev1.Namespace, pod corev1.Pod, globalEnabled return globalEnabled, nil } -// pointerToInt64 takes an int64 and returns a pointer to it. -func pointerToInt64(i int64) *int64 { - return &i -} - -// pointerToUInt64 takes an int64 and returns a pointer to it. -func pointerToUint64(i uint64) *uint64 { - return &i -} - -// pointerToBool takes a bool and returns a pointer to it. -func pointerToBool(b bool) *bool { - return &b -} - // splitCommaSeparatedItemsFromAnnotation takes an annotation and a pod // and returns the comma-separated value of the annotation as a list of strings. func splitCommaSeparatedItemsFromAnnotation(annotation string, pod corev1.Pod) []string { diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index 7e08756822..56b4f2192a 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -11,6 +11,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" ) const k8sNamespace = "k8snamespace" @@ -371,13 +372,13 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { pod.Annotations = c.annotations expectedSecurityContext := &corev1.SecurityContext{ - RunAsUser: pointerToInt64(0), - RunAsGroup: pointerToInt64(0), - Privileged: pointerToBool(true), + RunAsUser: pointer.Int64(0), + RunAsGroup: pointer.Int64(0), + Privileged: pointer.Bool(true), Capabilities: &corev1.Capabilities{ Add: []corev1.Capability{netAdminCapability}, }, - RunAsNonRoot: pointerToBool(false), + RunAsNonRoot: pointer.Bool(false), } ns := testNS ns.Labels = c.namespaceLabel @@ -1166,10 +1167,10 @@ func TestHandlerInitCopyContainer(t *testing.T) { require.Nil(t, container.SecurityContext) } else { expectedSecurityContext := &corev1.SecurityContext{ - RunAsUser: pointerToInt64(copyContainerUserAndGroupID), - RunAsGroup: pointerToInt64(copyContainerUserAndGroupID), - RunAsNonRoot: pointerToBool(true), - ReadOnlyRootFilesystem: pointerToBool(true), + RunAsUser: pointer.Int64(copyContainerUserAndGroupID), + RunAsGroup: pointer.Int64(copyContainerUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), } require.Equal(t, expectedSecurityContext, container.SecurityContext) } diff --git a/control-plane/connect-inject/envoy_sidecar.go b/control-plane/connect-inject/envoy_sidecar.go index c50fbac5ff..7bf55afe60 100644 --- a/control-plane/connect-inject/envoy_sidecar.go +++ b/control-plane/connect-inject/envoy_sidecar.go @@ -9,6 +9,7 @@ import ( "github.com/google/shlex" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" + "k8s.io/utils/pointer" ) func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, mpi multiPortInfo) (corev1.Container, error) { @@ -84,10 +85,10 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m } } container.SecurityContext = &corev1.SecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), - RunAsGroup: pointerToInt64(envoyUserAndGroupID), - RunAsNonRoot: pointerToBool(true), - ReadOnlyRootFilesystem: pointerToBool(true), + RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), } } diff --git a/control-plane/connect-inject/envoy_sidecar_test.go b/control-plane/connect-inject/envoy_sidecar_test.go index 8baa0d30b9..cd83d74244 100644 --- a/control-plane/connect-inject/envoy_sidecar_test.go +++ b/control-plane/connect-inject/envoy_sidecar_test.go @@ -8,6 +8,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" ) func TestHandlerEnvoySidecar(t *testing.T) { @@ -137,20 +138,20 @@ func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { tproxyEnabled: false, openShiftEnabled: false, expSecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), - RunAsGroup: pointerToInt64(envoyUserAndGroupID), - RunAsNonRoot: pointerToBool(true), - ReadOnlyRootFilesystem: pointerToBool(true), + RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), }, }, "tproxy enabled; openshift disabled": { tproxyEnabled: true, openShiftEnabled: false, expSecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), - RunAsGroup: pointerToInt64(envoyUserAndGroupID), - RunAsNonRoot: pointerToBool(true), - ReadOnlyRootFilesystem: pointerToBool(true), + RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), }, }, "tproxy disabled; openshift enabled": { @@ -162,10 +163,10 @@ func TestHandlerEnvoySidecar_withSecurityContext(t *testing.T) { tproxyEnabled: true, openShiftEnabled: true, expSecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), - RunAsGroup: pointerToInt64(envoyUserAndGroupID), - RunAsNonRoot: pointerToBool(true), - ReadOnlyRootFilesystem: pointerToBool(true), + RunAsUser: pointer.Int64(envoyUserAndGroupID), + RunAsGroup: pointer.Int64(envoyUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + ReadOnlyRootFilesystem: pointer.Bool(true), }, }, } @@ -210,7 +211,7 @@ func TestHandlerEnvoySidecar_FailsWithDuplicatePodSecurityContextUID(t *testing. }, }, SecurityContext: &corev1.PodSecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(envoyUserAndGroupID), }, }, } @@ -238,14 +239,14 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te Name: "web", // Setting RunAsUser: 1 should succeed. SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(1), + RunAsUser: pointer.Int64(1), }, }, { Name: "app", // Setting RunAsUser: 5995 should fail. SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(envoyUserAndGroupID), }, Image: "not-envoy", }, @@ -265,14 +266,14 @@ func TestHandlerEnvoySidecar_FailsWithDuplicateContainerSecurityContextUID(t *te Name: "web", // Setting RunAsUser: 1 should succeed. SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(1), + RunAsUser: pointer.Int64(1), }, }, { Name: "sidecar", // Setting RunAsUser: 5995 should succeed if the image matches h.ImageEnvoy. SecurityContext: &corev1.SecurityContext{ - RunAsUser: pointerToInt64(envoyUserAndGroupID), + RunAsUser: pointer.Int64(envoyUserAndGroupID), }, Image: "envoy", }, diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index 97b12e75a4..c124c08b55 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -15,6 +15,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -257,7 +258,7 @@ func (r *PeeringAcceptorController) updateStatus(ctx context.Context, acceptorOb return err } if acceptor.Status.LatestPeeringVersion == nil || *acceptor.Status.LatestPeeringVersion < peeringVersion { - acceptor.Status.LatestPeeringVersion = pointerToUint64(peeringVersion) + acceptor.Status.LatestPeeringVersion = pointer.Uint64(peeringVersion) } } err := r.Status().Update(ctx, acceptor) diff --git a/control-plane/connect-inject/peering_acceptor_controller_test.go b/control-plane/connect-inject/peering_acceptor_controller_test.go index 87629a48e9..7e649c2394 100644 --- a/control-plane/connect-inject/peering_acceptor_controller_test.go +++ b/control-plane/connect-inject/peering_acceptor_controller_test.go @@ -19,6 +19,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -294,7 +295,7 @@ func TestReconcile_CreateUpdatePeeringAcceptor(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(2), + LatestPeeringVersion: pointer.Uint64(2), }, expectedConsulPeerings: []*api.Peering{ { @@ -774,7 +775,7 @@ func TestReconcile_VersionAnnotation(t *testing.T) { }, ResourceVersion: "some-old-sha", }, - LatestPeeringVersion: pointerToUint64(3), + LatestPeeringVersion: pointer.Uint64(3), }, }, "is no/op if annotation value is equal to value in status": { @@ -790,7 +791,7 @@ func TestReconcile_VersionAnnotation(t *testing.T) { }, ResourceVersion: "some-old-sha", }, - LatestPeeringVersion: pointerToUint64(3), + LatestPeeringVersion: pointer.Uint64(3), }, }, "updates if annotation value is greater than value in status": { @@ -805,7 +806,7 @@ func TestReconcile_VersionAnnotation(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(4), + LatestPeeringVersion: pointer.Uint64(4), }, }, } @@ -836,7 +837,7 @@ func TestReconcile_VersionAnnotation(t *testing.T) { }, ResourceVersion: "some-old-sha", }, - LatestPeeringVersion: pointerToUint64(3), + LatestPeeringVersion: pointer.Uint64(3), }, } secret := createSecret("acceptor-created-secret", "default", "data", "some-data") diff --git a/control-plane/connect-inject/peering_dialer_controller.go b/control-plane/connect-inject/peering_dialer_controller.go index 0ed3dacea2..aa1fb4e0db 100644 --- a/control-plane/connect-inject/peering_dialer_controller.go +++ b/control-plane/connect-inject/peering_dialer_controller.go @@ -15,6 +15,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" @@ -213,7 +214,7 @@ func (r *PeeringDialerController) updateStatus(ctx context.Context, dialerObjKey return err } if dialer.Status.LatestPeeringVersion == nil || *dialer.Status.LatestPeeringVersion < peeringVersion { - dialer.Status.LatestPeeringVersion = pointerToUint64(peeringVersion) + dialer.Status.LatestPeeringVersion = pointer.Uint64(peeringVersion) } } err := r.Status().Update(ctx, dialer) diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index 39f0a8344f..120618eafd 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -17,6 +17,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/utils/pointer" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -239,7 +240,7 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(2), + LatestPeeringVersion: pointer.Uint64(2), }, peeringExists: true, }, @@ -390,7 +391,7 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(3), + LatestPeeringVersion: pointer.Uint64(3), }, }, "is no/op if annotation value is equal to value in status": { @@ -405,7 +406,7 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(3), + LatestPeeringVersion: pointer.Uint64(3), }, }, "updates if annotation value is greater than value in status": { @@ -420,7 +421,7 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { Backend: "kubernetes", }, }, - LatestPeeringVersion: pointerToUint64(4), + LatestPeeringVersion: pointer.Uint64(4), }, }, } @@ -466,7 +467,7 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { }, ResourceVersion: "latest-version", }, - LatestPeeringVersion: pointerToUint64(3), + LatestPeeringVersion: pointer.Uint64(3), }, } // Create fake k8s client diff --git a/control-plane/go.mod b/control-plane/go.mod index 20e4a034ca..742f7df71d 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -122,7 +122,7 @@ require ( k8s.io/apiextensions-apiserver v0.22.2 // indirect k8s.io/component-base v0.22.2 // indirect k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect - k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect + k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/control-plane/go.sum b/control-plane/go.sum index 15fd29f9a8..4bcd31929e 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -1017,6 +1017,8 @@ k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2R k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 h1:XmRqFcQlCy/lKRZ39j+RVpokYNroHPqV3mcBRfnhT5o= +k8s.io/utils v0.0.0-20220812165043-ad590609e2e5/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= From 894b52a3c2f00d9c46bb0aa86ad6ba1fa46e4f15 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 15 Aug 2022 14:30:33 -0400 Subject: [PATCH 088/235] Use new GitHub Markdown note syntax (#1424) --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a25910b9a..ae543ca226 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,8 @@ for each feature will be noted below. By versioning this project separately, we can iterate on Kubernetes integrations more quickly and release new versions without forcing Consul users to do a full Consul upgrade. -> :warning: **Please note**: We take Consul's security and our users' trust very seriously. If +> **Note** +> We take Consul's security and our users' trust very seriously. If you believe you have found a security issue in Consul K8s, _please responsibly disclose_ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). From 690c9946baf230e15367e156abec542d6428178d Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Mon, 15 Aug 2022 15:53:04 -0600 Subject: [PATCH 089/235] Various acceptance tests fixes (#1414) - parallelize nightly tests (they now take ~5h which is the max time circleci will allow us to run w/o output) - re-establish port forwarding if we lose connection. Sometimes, we lose port-forwarding connection and never re-establish it, which leads to any calls to consul to fail. Instead, we now monitor the local port, and if we can't connect to it, we re-establish port-forwarding - Add retries to aws cleanup script --- .circleci/config.yml | 6 ++- acceptance/framework/consul/helm_cluster.go | 42 ++++++++++++++++++++- acceptance/framework/k8s/helpers.go | 4 +- hack/aws-acceptance-test-cleanup/main.go | 33 ++++++++++------ 4 files changed, 70 insertions(+), 15 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 88649ec789..0ddc7c8302 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -129,8 +129,8 @@ commands: echo "Running $pkgs" gotestsum --junitfile "$TEST_RESULTS/gotestsum-report.xml" -- $pkgs -p 1 -timeout 2h -failfast \ << parameters.additional-flags >> \ - -enable-multi-cluster \ ${ENABLE_ENTERPRISE:+-enable-enterprise} \ + -enable-multi-cluster \ -debug-directory="$TEST_RESULTS/debug" \ -consul-k8s-image=<< parameters.consul-k8s-image >> @@ -604,6 +604,7 @@ jobs: # ACCEPTANCE TESTS ######################## acceptance-gke-1-20: + parallelism: 6 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -670,6 +671,7 @@ jobs: failure_message: "GKE acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" acceptance-aks-1-21: + parallelism: 6 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -725,6 +727,7 @@ jobs: failure_message: "AKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" acceptance-eks-1-19: + parallelism: 6 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -839,6 +842,7 @@ jobs: failure_message: "OpenShift acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" acceptance-kind-1-23: + parallelism: 6 environment: - TEST_RESULTS: /tmp/test-results machine: diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index 8a41f994e5..085ceda493 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -3,6 +3,7 @@ package consul import ( "context" "fmt" + "net" "strings" "testing" "time" @@ -297,12 +298,51 @@ func (h *HelmCluster) CreatePortForwardTunnelToResourcePort(t *testing.T, resour require.NoError(r, tunnel.ForwardPortE(t)) }) + doneChan := make(chan bool) + t.Cleanup(func() { - tunnel.Close() + close(doneChan) }) + go h.monitorPortForwardedServer(t, localPort, tunnel, doneChan, resourceName, remotePort) + return fmt.Sprintf("127.0.0.1:%d", localPort) +} +func (h *HelmCluster) monitorPortForwardedServer(t *testing.T, port int, tunnel *terratestk8s.Tunnel, doneChan chan bool, resourceName string, remotePort int) { + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + for { + select { + case <-doneChan: + logger.Log(t, "stopping monitor of the port-forwarded server") + tunnel.Close() + return + case <-ticker.C: + conn, err := net.Dial("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + if err != nil { + logger.Log(t, "lost connection to port-forwarded server; restarting port-forwarding", "port", port) + tunnel.Close() + tunnel = terratestk8s.NewTunnelWithLogger( + h.helmOptions.KubectlOptions, + terratestk8s.ResourceTypePod, + resourceName, + port, + remotePort, + h.logger) + err = tunnel.ForwardPortE(t) + if err != nil { + // If we couldn't establish a port forwarding channel, continue, so we can try again. + continue + } + } + if conn != nil { + // Ignore error because we don't care if connection is closed successfully or not. + _ = conn.Close() + } + } + } } func (h *HelmCluster) SetupConsulClient(t *testing.T, secure bool) (client *api.Client, configAddress string) { diff --git a/acceptance/framework/k8s/helpers.go b/acceptance/framework/k8s/helpers.go index 3f981336ee..8d3da64612 100644 --- a/acceptance/framework/k8s/helpers.go +++ b/acceptance/framework/k8s/helpers.go @@ -109,8 +109,8 @@ func ServiceHost(t *testing.T, cfg *config.TestConfig, ctx environment.TestConte } else { var host string // It can take some time for the load balancers to be ready and have an IP/Hostname. - // Wait for 60 seconds before failing. - retry.RunWith(&retry.Counter{Wait: 1 * time.Second, Count: 60}, t, func(r *retry.R) { + // Wait for 5 minutes before failing. + retry.RunWith(&retry.Counter{Wait: 1 * time.Second, Count: 600}, t, func(r *retry.R) { svc, err := ctx.KubernetesClient(t).CoreV1().Services(ctx.KubectlOptions(t).Namespace).Get(context.Background(), serviceName, metav1.GetOptions{}) require.NoError(t, err) require.NotEmpty(r, svc.Status.LoadBalancer.Ingress) diff --git a/hack/aws-acceptance-test-cleanup/main.go b/hack/aws-acceptance-test-cleanup/main.go index d5932d8978..b72b88c12f 100644 --- a/hack/aws-acceptance-test-cleanup/main.go +++ b/hack/aws-acceptance-test-cleanup/main.go @@ -363,8 +363,6 @@ func realMain(ctx context.Context) error { }); err != nil { return err } - // Allow time for ELB deletion to propagate so that we can detach the internet gateway. - time.Sleep(30 * time.Second) fmt.Printf("ELB: Destroyed [id=%s]\n", *elbDescrip.LoadBalancerName) } @@ -379,11 +377,17 @@ func realMain(ctx context.Context) error { }) for _, igw := range igws.InternetGateways { fmt.Printf("Internet gateway: Detaching from VPC... [id=%s]\n", *igw.InternetGatewayId) - _, err := ec2Client.DetachInternetGatewayWithContext(ctx, &ec2.DetachInternetGatewayInput{ - InternetGatewayId: igw.InternetGatewayId, - VpcId: vpcID, - }) - if err != nil { + if err := destroyBackoff(ctx, "Internet Gateway", *igw.InternetGatewayId, func() error { + _, err := ec2Client.DetachInternetGatewayWithContext(ctx, &ec2.DetachInternetGatewayInput{ + InternetGatewayId: igw.InternetGatewayId, + VpcId: vpcID, + }) + if err != nil { + return err + } + + return nil + }); err != nil { return err } fmt.Printf("Internet gateway: Detached [id=%s]\n", *igw.InternetGatewayId) @@ -409,12 +413,19 @@ func realMain(ctx context.Context) error { }) for _, subnet := range subnets.Subnets { fmt.Printf("Subnet: Destroying... [id=%s]\n", *subnet.SubnetId) - _, err := ec2Client.DeleteSubnetWithContext(ctx, &ec2.DeleteSubnetInput{ - SubnetId: subnet.SubnetId, - }) - if err != nil { + if err := destroyBackoff(ctx, "Subnet", *subnet.SubnetId, func() error { + _, err := ec2Client.DeleteSubnetWithContext(ctx, &ec2.DeleteSubnetInput{ + SubnetId: subnet.SubnetId, + }) + if err != nil { + return err + } + + return nil + }); err != nil { return err } + fmt.Printf("Subnet: Destroyed [id=%s]\n", *subnet.SubnetId) } From 49a04f1881f5a21dec3e9f0f853b41bbeb130a6c Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Tue, 16 Aug 2022 12:52:54 -0400 Subject: [PATCH 090/235] Rename flag for peering token server addresses. (#1426) - The flag was initially named `server-address` but the `server-address` flag has been used across the project to imply ONLY the address of the external server when enabled. This meaning is overloaded in the context of the server address used for generating the peering token. This leads to errors (specifically in the agentless context), where the deployment must explicitly know the list of external servers. --- .../templates/connect-inject-deployment.yaml | 4 +-- .../test/unit/connect-inject-deployment.bats | 26 +++++++++---------- control-plane/go.mod | 2 +- control-plane/go.sum | 4 --- .../subcommand/inject-connect/command.go | 8 +++--- 5 files changed, 20 insertions(+), 24 deletions(-) diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 266eeb4994..a5cae8edc5 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -148,14 +148,14 @@ spec: {{- if .Values.externalServers.enabled }} {{- $port := .Values.externalServers.grpcPort }} {{- range $h := .Values.externalServers.hosts }} - -server-address="{{ $h }}:{{ $port }}" \ + -token-server-address="{{ $h }}:{{ $port }}" \ {{- end }} {{- end }} {{- end }} {{- end }} {{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "static") }} {{- range $addr := .Values.global.peering.tokenGeneration.serverAddresses.static }} - -server-address="{{ $addr }}" \ + -token-server-address="{{ $addr }}" \ {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 52552c6721..22464ae1b4 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1907,7 +1907,7 @@ EOF [[ "$output" =~ "global.peering.tokenGeneration.serverAddresses.source must be one of empty string, 'consul' or 'static'" ]] } -@test "connectInject/Deployment: -read-server-expose-service and -server-address is not set when global.peering.tokenGeneration.serverAddresses.source is consul" { +@test "connectInject/Deployment: -read-server-expose-service and -token-server-address is not set when global.peering.tokenGeneration.serverAddresses.source is consul" { cd `chart_dir` local command=$(helm template \ -s templates/connect-inject-deployment.yaml \ @@ -1920,11 +1920,11 @@ EOF local actual=$(echo $command | jq -r ' . | any(contains("-read-server-expose-service=true"))' | tee /dev/stderr) [ "${actual}" = "false" ] - local actual=$(echo $command | jq -r ' . | any(contains("-server-address"))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address"))' | tee /dev/stderr) [ "${actual}" = "false" ] } -@test "connectInject/Deployment: when servers are not enabled and externalServers.enabled=true, passes in -server-address flags with hosts" { +@test "connectInject/Deployment: when servers are not enabled and externalServers.enabled=true, passes in -token-server-address flags with hosts" { cd `chart_dir` local command=$(helm template \ -s templates/connect-inject-deployment.yaml \ @@ -1937,10 +1937,10 @@ EOF . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command') - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:8503\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"1.2.3.4:8503\""))' | tee /dev/stderr) [ "${actual}" = "true" ] - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:8503\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"2.2.3.4:8503\""))' | tee /dev/stderr) [ "${actual}" = "true" ] } @@ -1958,14 +1958,14 @@ EOF . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command') - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) [ "${actual}" = "true" ] - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:1234\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"2.2.3.4:1234\""))' | tee /dev/stderr) [ "${actual}" = "true" ] } -@test "connectInject/Deployment: when peering token generation source is static passes in -server-address flags with static addresses" { +@test "connectInject/Deployment: when peering token generation source is static passes in -token-server-address flags with static addresses" { cd `chart_dir` local command=$(helm template \ -s templates/connect-inject-deployment.yaml \ @@ -1977,14 +1977,14 @@ EOF . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command') - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) [ "${actual}" = "true" ] - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:2234\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"2.2.3.4:2234\""))' | tee /dev/stderr) [ "${actual}" = "true" ] } -@test "connectInject/Deployment: when peering token generation source is static and externalHosts are set, passes in -server-address flags with static addresses, not externalServers.hosts" { +@test "connectInject/Deployment: when peering token generation source is static and externalHosts are set, passes in -token-server-address flags with static addresses, not externalServers.hosts" { cd `chart_dir` local command=$(helm template \ -s templates/connect-inject-deployment.yaml \ @@ -2000,10 +2000,10 @@ EOF . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command') - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"1.2.3.4:1234\""))' | tee /dev/stderr) [ "${actual}" = "true" ] - local actual=$(echo $command | jq -r ' . | any(contains("-server-address=\"2.2.3.4:2234\""))' | tee /dev/stderr) + local actual=$(echo $command | jq -r ' . | any(contains("-token-server-address=\"2.2.3.4:2234\""))' | tee /dev/stderr) [ "${actual}" = "true" ] } diff --git a/control-plane/go.mod b/control-plane/go.mod index 742f7df71d..1848c8f435 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -26,6 +26,7 @@ require ( k8s.io/apimachinery v0.22.2 k8s.io/client-go v0.22.2 k8s.io/klog/v2 v2.9.0 + k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 sigs.k8s.io/controller-runtime v0.10.2 ) @@ -122,7 +123,6 @@ require ( k8s.io/apiextensions-apiserver v0.22.2 // indirect k8s.io/component-base v0.22.2 // indirect k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect - k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect sigs.k8s.io/yaml v1.2.0 // indirect ) diff --git a/control-plane/go.sum b/control-plane/go.sum index 4bcd31929e..03ca166926 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -296,12 +296,9 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c h1:lEMAoMGwTncIh9opSHvvGxM0WrNT5YuCbKipwtU7UNs= -github.com/hashicorp/consul/api v1.10.1-0.20220725163158-2da8949d788c/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk= github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51 h1:jLjJ0p6QaJFg0PJjWcx+qWTTMujanlJRIRJl15jvG8I= github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= @@ -1015,7 +1012,6 @@ k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20220812165043-ad590609e2e5 h1:XmRqFcQlCy/lKRZ39j+RVpokYNroHPqV3mcBRfnhT5o= k8s.io/utils v0.0.0-20220812165043-ad590609e2e5/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index 1b4de11afb..008cb8b400 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -96,7 +96,7 @@ type Command struct { // Server address flags. flagReadServerExposeService bool - flagServerAddresses []string + flagTokenServerAddresses []string // Transparent proxy flags. flagDefaultEnableTransparentProxy bool @@ -195,8 +195,8 @@ func (c *Command) init() { "Enable or disable JSON output format for logging.") c.flagSet.BoolVar(&c.flagReadServerExposeService, "read-server-expose-service", false, "Enables polling the Consul servers' external service for its IP(s).") - c.flagSet.Var((*flags.AppendSliceValue)(&c.flagServerAddresses), "server-address", - "An address of the Consul server(s), formatted host:port, where host may be an IP or DNS name and port must be a gRPC port. May be specified multiple times for multiple addresses.") + c.flagSet.Var((*flags.AppendSliceValue)(&c.flagTokenServerAddresses), "token-server-address", + "An address of the Consul server(s) as saved in the peering token, formatted host:port, where host may be an IP or DNS name and port must be a gRPC port. May be specified multiple times for multiple addresses.") // Proxy sidecar resource setting flags. c.flagSet.StringVar(&c.flagDefaultSidecarProxyCPURequest, "default-sidecar-proxy-cpu-request", "", "Default sidecar proxy CPU request.") @@ -452,7 +452,7 @@ func (c *Command) Run(args []string) int { ConsulClient: c.consulClient, ExposeServersServiceName: c.flagResourcePrefix + "-expose-servers", ReadServerExternalService: c.flagReadServerExposeService, - TokenServerAddresses: c.flagServerAddresses, + TokenServerAddresses: c.flagTokenServerAddresses, ReleaseNamespace: c.flagReleaseNamespace, Log: ctrl.Log.WithName("controller").WithName("peering-acceptor"), Scheme: mgr.GetScheme(), From ea8c5057976791070affb8664ced23916e0e0416 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Tue, 16 Aug 2022 14:23:18 -0400 Subject: [PATCH 091/235] Fix acceptance tests passing "-config" instead of "-kubeconfig" to CLI (#1427) * config -> kubeconfig * Run GKE Acceptance * Stop GKE acceptance tests running on PRs --- acceptance/framework/cli/cli.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acceptance/framework/cli/cli.go b/acceptance/framework/cli/cli.go index 11f55ade1d..81fe353525 100644 --- a/acceptance/framework/cli/cli.go +++ b/acceptance/framework/cli/cli.go @@ -33,7 +33,7 @@ func (c *CLI) Run(t *testing.T, options *k8s.KubectlOptions, args ...string) ([] // Append configuration from `options` to the command. if options.ConfigPath != "" { - args = append(args, "-config", options.ConfigPath) + args = append(args, "-kubeconfig", options.ConfigPath) } if options.ContextName != "" { args = append(args, "-context", options.ContextName) From c930471749131b81ab0e6cc19173a081849ceef1 Mon Sep 17 00:00:00 2001 From: David Yu Date: Tue, 16 Aug 2022 17:18:08 -0700 Subject: [PATCH 092/235] values.yaml: add more detail around using connectCA with vault namespaces (#1430) * values.yaml: add more detail around using connectCA with vault namespaces Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com> --- charts/consul/values.yaml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index dd38152c80..84b50a6400 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -271,16 +271,16 @@ global: authMethodPath: "kubernetes" # The path to a PKI secrets engine for the root certificate. - # Please see https://www.consul.io/docs/connect/ca/vault#rootpkipath. + # For more details, please refer to [Vault Connect CA configuration](https://www.consul.io/docs/connect/ca/vault#rootpkipath). rootPKIPath: "" # The path to a PKI secrets engine for the generated intermediate certificate. - # Please see https://www.consul.io/docs/connect/ca/vault#intermediatepkipath. + # For more details, please refer to [Vault Connect CA configuration](https://www.consul.io/docs/connect/ca/vault#intermediatepkipath). intermediatePKIPath: "" # Additional Connect CA configuration in JSON format. - # Please see https://www.consul.io/docs/connect/ca/vault#common-ca-config-options - # for additional configuration options. + # Please refer to [Vault Connect CA configuration](https://www.consul.io/docs/connect/ca/vault#configuration) + # for all configuration options available for that provider. # # Example: # @@ -289,6 +289,7 @@ global: # { # "connect": [{ # "ca_config": [{ + # "namespace": "my-vault-ns", # "leaf_cert_ttl": "36h" # }] # }] From cbc0e4cb3acca4c77ac1179d34f7b59b47d64f2c Mon Sep 17 00:00:00 2001 From: Alvin Huang <17609145+alvin-huang@users.noreply.github.com> Date: Wed, 17 Aug 2022 12:06:25 -0400 Subject: [PATCH 093/235] set PRODUCT_VERSION for default docker build (#1429) --- control-plane/Dockerfile | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index f572d37413..73926fdf69 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -66,22 +66,20 @@ CMD /bin/${BIN_NAME} # reproducible currently. FROM alpine:3.16 AS release-default -# NAME and VERSION are the name of the software in releases.hashicorp.com -# and the version to download. Example: NAME=consul VERSION=1.2.3. ARG BIN_NAME=consul-k8s-control-plane -ARG VERSION +ARG PRODUCT_VERSION LABEL name=${BIN_NAME} \ maintainer="Team Consul Kubernetes " \ vendor="HashiCorp" \ - version=${VERSION} \ - release=${VERSION} \ + version=${PRODUCT_VERSION} \ + release=${PRODUCT_VERSION} \ summary="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." \ description="consul-k8s-control-plane provides first-class integrations between Consul and Kubernetes." # Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD ENV BIN_NAME=${BIN_NAME} -ENV VERSION=${VERSION} +ENV VERSION=${PRODUCT_VERSION} RUN apk add --no-cache ca-certificates curl gnupg libcap openssl su-exec iputils libc6-compat iptables @@ -132,7 +130,7 @@ LABEL name=$PRODUCT_NAME \ # Set ARGs as ENV so that they can be used in ENTRYPOINT/CMD ENV NAME=${BIN_NAME} -ENV VERSION=${VERSION} +ENV VERSION=${PRODUCT_VERSION} # TARGETOS and TARGETARCH are set automatically when --platform is provided. ARG TARGETOS From 315fd9f63178d436b4e2ffe297e899f8e562b6d3 Mon Sep 17 00:00:00 2001 From: Dan Stough Date: Wed, 17 Aug 2022 13:56:04 -0400 Subject: [PATCH 094/235] test: egress destination tests (#1383) --- .../anyuid-scc-rolebinding.yaml | 11 ++ .../bases/static-server-https/configmap.yaml | 19 ++ .../bases/static-server-https/deployment.yaml | 37 ++++ .../static-server-https/kustomization.yaml | 8 + .../privileged-scc-rolebinding.yaml | 11 ++ .../static-server-https/psp-rolebinding.yaml | 11 ++ .../bases/static-server-https/service.yaml | 18 ++ .../static-server-https/serviceaccount.yaml | 4 + .../tests/terminating-gateway/common.go | 96 +++++++++ .../terminating_gateway_destinations_test.go | 183 ++++++++++++++++++ .../terminating_gateway_namespaces_test.go | 24 ++- .../terminating_gateway_test.go | 93 +-------- 12 files changed, 422 insertions(+), 93 deletions(-) create mode 100644 acceptance/tests/fixtures/bases/static-server-https/anyuid-scc-rolebinding.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/configmap.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/deployment.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/kustomization.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/privileged-scc-rolebinding.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/psp-rolebinding.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/service.yaml create mode 100644 acceptance/tests/fixtures/bases/static-server-https/serviceaccount.yaml create mode 100644 acceptance/tests/terminating-gateway/common.go create mode 100644 acceptance/tests/terminating-gateway/terminating_gateway_destinations_test.go diff --git a/acceptance/tests/fixtures/bases/static-server-https/anyuid-scc-rolebinding.yaml b/acceptance/tests/fixtures/bases/static-server-https/anyuid-scc-rolebinding.yaml new file mode 100644 index 0000000000..d224a082da --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/anyuid-scc-rolebinding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: static-server-openshift-anyuid +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:openshift:scc:anyuid +subjects: + - kind: ServiceAccount + name: static-server \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/static-server-https/configmap.yaml b/acceptance/tests/fixtures/bases/static-server-https/configmap.yaml new file mode 100644 index 0000000000..dcb975978e --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/configmap.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: static-server-config +data: + config: | + { + local_certs + skip_install_trust + auto_https disable_redirects + } + static-server.default { + log + respond "hello world" + } + :80 { + log + respond "hello world" + } \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/static-server-https/deployment.yaml b/acceptance/tests/fixtures/bases/static-server-https/deployment.yaml new file mode 100644 index 0000000000..3071162c15 --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/deployment.yaml @@ -0,0 +1,37 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: static-server +spec: + replicas: 1 + selector: + matchLabels: + app: static-server + template: + metadata: + labels: + app: static-server + spec: + containers: + - name: caddy + image: caddy:latest + ports: + - name: https-port + containerPort: 443 + - name: http-port + containerPort: 80 + volumeMounts: + - name: data + mountPath: "/data" + - name: config + mountPath: /etc/caddy/ + readOnly: true + volumes: + - name: data + emptyDir: {} + - name: config + configMap: + name: static-server-config + items: + - key: "config" + path: "Caddyfile" \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/static-server-https/kustomization.yaml b/acceptance/tests/fixtures/bases/static-server-https/kustomization.yaml new file mode 100644 index 0000000000..78508b7938 --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - deployment.yaml + - configmap.yaml + - service.yaml + - serviceaccount.yaml + - psp-rolebinding.yaml + - anyuid-scc-rolebinding.yaml + - privileged-scc-rolebinding.yaml \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/static-server-https/privileged-scc-rolebinding.yaml b/acceptance/tests/fixtures/bases/static-server-https/privileged-scc-rolebinding.yaml new file mode 100644 index 0000000000..1b9fe13789 --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/privileged-scc-rolebinding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: static-server-openshift-privileged +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:openshift:scc:privileged +subjects: + - kind: ServiceAccount + name: static-server \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/static-server-https/psp-rolebinding.yaml b/acceptance/tests/fixtures/bases/static-server-https/psp-rolebinding.yaml new file mode 100644 index 0000000000..acccd2fcec --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/psp-rolebinding.yaml @@ -0,0 +1,11 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: static-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: test-psp +subjects: + - kind: ServiceAccount + name: static-server \ No newline at end of file diff --git a/acceptance/tests/fixtures/bases/static-server-https/service.yaml b/acceptance/tests/fixtures/bases/static-server-https/service.yaml new file mode 100644 index 0000000000..168c90d3d0 --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: static-server + labels: + app: static-server +spec: + ports: + - name: https-port + port: 443 + targetPort: https-port + protocol: TCP + - name: http-port + port: 80 + targetPort: http-port + protocol: TCP + selector: + app: static-server diff --git a/acceptance/tests/fixtures/bases/static-server-https/serviceaccount.yaml b/acceptance/tests/fixtures/bases/static-server-https/serviceaccount.yaml new file mode 100644 index 0000000000..f4267a573e --- /dev/null +++ b/acceptance/tests/fixtures/bases/static-server-https/serviceaccount.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: static-server diff --git a/acceptance/tests/terminating-gateway/common.go b/acceptance/tests/terminating-gateway/common.go new file mode 100644 index 0000000000..b94dd8a897 --- /dev/null +++ b/acceptance/tests/terminating-gateway/common.go @@ -0,0 +1,96 @@ +package terminatinggateway + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/consul-k8s/acceptance/framework/logger" + "github.com/hashicorp/consul/api" + "github.com/stretchr/testify/require" +) + +const ( + staticClientName = "static-client" + staticServerName = "static-server" + staticServerLocalAddress = "http://localhost:1234" +) + +func addIntention(t *testing.T, consulClient *api.Client, sourceNS, sourceService, destinationNS, destinationsService string) { + t.Helper() + + logger.Log(t, fmt.Sprintf("creating %s => %s intention", sourceService, destinationsService)) + _, _, err := consulClient.ConfigEntries().Set(&api.ServiceIntentionsConfigEntry{ + Kind: api.ServiceIntentions, + Name: destinationsService, + Namespace: destinationNS, + Sources: []*api.SourceIntention{ + { + Name: sourceService, + Namespace: sourceNS, + Action: api.IntentionActionAllow, + }, + }, + }, nil) + require.NoError(t, err) +} + +func createTerminatingGatewayConfigEntry(t *testing.T, consulClient *api.Client, gwNamespace, serviceNamespace string, serviceNames ...string) { + t.Helper() + + logger.Log(t, "creating config entry") + + if serviceNamespace != "" { + logger.Logf(t, "creating the %s namespace in Consul", serviceNamespace) + _, _, err := consulClient.Namespaces().Create(&api.Namespace{ + Name: serviceNamespace, + }, nil) + require.NoError(t, err) + } + + var gatewayServices []api.LinkedService + for _, serviceName := range serviceNames { + linkedService := api.LinkedService{Name: serviceName, Namespace: serviceNamespace} + gatewayServices = append(gatewayServices, linkedService) + } + + configEntry := &api.TerminatingGatewayConfigEntry{ + Kind: api.TerminatingGateway, + Name: "terminating-gateway", + Namespace: gwNamespace, + Services: gatewayServices, + } + + created, _, err := consulClient.ConfigEntries().Set(configEntry, nil) + require.NoError(t, err) + require.True(t, created, "failed to create config entry") +} + +func updateTerminatingGatewayRole(t *testing.T, consulClient *api.Client, rules string) { + t.Helper() + + logger.Log(t, "creating a write policy for the static-server") + _, _, err := consulClient.ACL().PolicyCreate(&api.ACLPolicy{ + Name: "static-server-write-policy", + Rules: rules, + }, nil) + require.NoError(t, err) + + logger.Log(t, "getting the terminating gateway role") + roles, _, err := consulClient.ACL().RoleList(nil) + require.NoError(t, err) + terminatingGatewayRoleID := "" + for _, role := range roles { + if strings.Contains(role.Name, "terminating-gateway") { + terminatingGatewayRoleID = role.ID + break + } + } + + logger.Log(t, "update role with policy") + termGwRole, _, err := consulClient.ACL().RoleRead(terminatingGatewayRoleID, nil) + require.NoError(t, err) + termGwRole.Policies = append(termGwRole.Policies, &api.ACLTokenPolicyLink{Name: "static-server-write-policy"}) + _, _, err = consulClient.ACL().RoleUpdate(termGwRole, nil) + require.NoError(t, err) +} diff --git a/acceptance/tests/terminating-gateway/terminating_gateway_destinations_test.go b/acceptance/tests/terminating-gateway/terminating_gateway_destinations_test.go new file mode 100644 index 0000000000..d18d971743 --- /dev/null +++ b/acceptance/tests/terminating-gateway/terminating_gateway_destinations_test.go @@ -0,0 +1,183 @@ +package terminatinggateway + +import ( + "fmt" + "github.com/hashicorp/consul/api" + "github.com/hashicorp/go-version" + "github.com/stretchr/testify/require" + "strconv" + "testing" + + "github.com/hashicorp/consul-k8s/acceptance/framework/consul" + "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" + "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" + "github.com/hashicorp/consul-k8s/acceptance/framework/logger" +) + +// Test that egress Destinations route through terminating gateways. +// Destinations are only valid when operating in transparent mode. +func TestTerminatingGatewayDestinations(t *testing.T) { + cfg := suite.Config() + if !cfg.EnableTransparentProxy { + t.Skipf("skipping this test because -enable-transparent-proxy is not set") + } + + ver, err := version.NewVersion("1.13.0") + require.NoError(t, err) + if cfg.ConsulVersion != nil && cfg.ConsulVersion.LessThan(ver) { + t.Skipf("skipping this test because Destinations are not supported in version %v", cfg.ConsulVersion.String()) + } + + const ( + staticServerServiceName = "static-server.default" + staticServerHostnameID = "static-server-hostname" + staticServerIPID = "static-server-ip" + terminatingGatewayRules = `service_prefix "static-server" { + policy = "write" + }` + ) + + cases := []struct { + secure bool + }{ + { + secure: false, + }, + { + secure: true, + }, + } + for _, c := range cases { + name := fmt.Sprintf("secure: %t", c.secure) + t.Run(name, func(t *testing.T) { + ctx := suite.Environment().DefaultContext(t) + + helmValues := map[string]string{ + "connectInject.enabled": "true", + "terminatingGateways.enabled": "true", + "terminatingGateways.gateways[0].name": "terminating-gateway", + "terminatingGateways.gateways[0].replicas": "1", + + "global.acls.manageSystemACLs": strconv.FormatBool(c.secure), + "global.tls.enabled": strconv.FormatBool(c.secure), + "global.tls.autoEncrypt": strconv.FormatBool(c.secure), + } + + logger.Log(t, "creating consul cluster") + releaseName := helpers.RandomName() + consulCluster := consul.NewHelmCluster(t, helmValues, ctx, cfg, releaseName) + consulCluster.Create(t) + consulClient, _ := consulCluster.SetupConsulClient(t, c.secure) + + // Deploy a static-server that will play the role of an external service. + logger.Log(t, "creating static-server deployment") + k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/bases/static-server-https") + + // If ACLs are enabled we need to update the role of the terminating gateway + // with service:write permissions to the static-server service + // so that it can request Connect certificates for it. + if c.secure { + updateTerminatingGatewayRole(t, consulClient, terminatingGatewayRules) + } + + // Since we are using the transparent kube DNS, disable the ability + // of the service to dial the server directly through the sidecar + createMeshConfigEntry(t, consulClient, "") + + // Create the config entry for the terminating gateway. + createTerminatingGatewayConfigEntry(t, consulClient, "", "", staticServerHostnameID, staticServerIPID) + + // Deploy the static client + logger.Log(t, "deploying static client") + k8s.DeployKustomize(t, ctx.KubectlOptions(t), cfg.NoCleanupOnFailure, cfg.DebugDirectory, "../fixtures/cases/static-client-tproxy") + + staticServerIP, err := k8s.RunKubectlAndGetOutputE(t, ctx.KubectlOptions(t), "get", "po", "-l", "app=static-server", `-o=jsonpath={.items[0].status.podIP}`) + require.NoError(t, err) + require.NotEmpty(t, staticServerIP) + + staticServerHostnameURL := fmt.Sprintf("https://%s", staticServerServiceName) + staticServerIPURL := fmt.Sprintf("http://%s", staticServerIP) + + // Create the service default declaring the external service (aka Destination) + logger.Log(t, "creating tcp-based service defaults") + createServiceDefaultDestination(t, consulClient, "", staticServerHostnameID, "", 443, staticServerServiceName) + createServiceDefaultDestination(t, consulClient, "", staticServerIPID, "", 80, staticServerIP) + + // If ACLs are enabled, test that intentions prevent connections. + if c.secure { + // With the terminating gateway up, we test that we can make a call to it + // via the static-server. It should fail to connect with the + // static-server pod because of intentions. + logger.Log(t, "testing intentions prevent connections through the terminating gateway") + k8s.CheckStaticServerConnectionFailing(t, ctx.KubectlOptions(t), staticClientName, staticServerIPURL) + k8s.CheckStaticServerConnectionFailing(t, ctx.KubectlOptions(t), staticClientName, "-k", staticServerHostnameURL) + + logger.Log(t, "adding intentions to allow traffic from client ==> server") + addIntention(t, consulClient, "", staticClientName, "", staticServerHostnameID) + addIntention(t, consulClient, "", staticClientName, "", staticServerIPID) + } + + // Test that we can make a call to the terminating gateway. + logger.Log(t, "trying calls to terminating gateway") + k8s.CheckStaticServerConnectionSuccessful(t, ctx.KubectlOptions(t), staticClientName, staticServerIPURL) + k8s.CheckStaticServerConnectionSuccessful(t, ctx.KubectlOptions(t), staticClientName, "-k", staticServerHostnameURL) + + // Try running some different scenarios + staticServerHostnameURL = fmt.Sprintf("http://%s", staticServerServiceName) + staticServerIPURL = fmt.Sprintf("http://%s", staticServerIP) + + // Update the service default declaring the external service (aka Destination) + logger.Log(t, "updating service defaults to try other scenarios") + + // You can't use TLS w/ protocol set to anything L7; Envoy can't snoop the traffic when the client encrypts it + createServiceDefaultDestination(t, consulClient, "", staticServerHostnameID, "http", 80, staticServerServiceName) + createServiceDefaultDestination(t, consulClient, "", staticServerIPID, "http", 80, staticServerIP) + + logger.Log(t, "trying calls to terminating gateway") + k8s.CheckStaticServerConnectionSuccessful(t, ctx.KubectlOptions(t), staticClientName, staticServerIPURL) + k8s.CheckStaticServerConnectionSuccessful(t, ctx.KubectlOptions(t), staticClientName, staticServerHostnameURL) + }) + } +} +func createServiceDefaultDestination(t *testing.T, consulClient *api.Client, serviceNamespace string, name string, protocol string, port int, addresses ...string) { + t.Helper() + + logger.Log(t, "creating config entry") + + if serviceNamespace != "" { + logger.Logf(t, "creating the %s namespace in Consul", serviceNamespace) + _, _, err := consulClient.Namespaces().Create(&api.Namespace{ + Name: serviceNamespace, + }, nil) + require.NoError(t, err) + } + + configEntry := &api.ServiceConfigEntry{ + Kind: api.ServiceDefaults, + Name: name, + Namespace: serviceNamespace, + Protocol: protocol, + Destination: &api.DestinationConfig{ + Addresses: addresses, + Port: port, + }, + } + + created, _, err := consulClient.ConfigEntries().Set(configEntry, nil) + require.NoError(t, err) + require.True(t, created, "failed to create config entry") +} + +func createMeshConfigEntry(t *testing.T, consulClient *api.Client, namespace string) { + t.Helper() + + logger.Log(t, "creating mesh config entry to enable MeshDestinationOnly") + created, _, err := consulClient.ConfigEntries().Set(&api.MeshConfigEntry{ + Namespace: namespace, + TransparentProxy: api.TransparentProxyMeshConfig{ + MeshDestinationsOnly: true, + }, + }, nil) + require.NoError(t, err) + require.True(t, created, "failed to create config entry") +} diff --git a/acceptance/tests/terminating-gateway/terminating_gateway_namespaces_test.go b/acceptance/tests/terminating-gateway/terminating_gateway_namespaces_test.go index 232c15d13d..7168fdd4e8 100644 --- a/acceptance/tests/terminating-gateway/terminating_gateway_namespaces_test.go +++ b/acceptance/tests/terminating-gateway/terminating_gateway_namespaces_test.go @@ -99,13 +99,13 @@ func TestTerminatingGatewaySingleNamespace(t *testing.T) { // If ACLs are enabled we need to update the role of the terminating gateway // with service:write permissions to the static-server service - // so that it can can request Connect certificates for it. + // so that it can request Connect certificates for it. if c.secure { updateTerminatingGatewayRole(t, consulClient, fmt.Sprintf(staticServerPolicyRulesNamespace, testNamespace)) } // Create the config entry for the terminating gateway. - createTerminatingGatewayConfigEntry(t, consulClient, testNamespace, testNamespace) + createTerminatingGatewayConfigEntry(t, consulClient, testNamespace, testNamespace, staticServerName) // Deploy the static client. logger.Log(t, "deploying static client") @@ -116,12 +116,16 @@ func TestTerminatingGatewaySingleNamespace(t *testing.T) { // With the terminating gateway up, we test that we can make a call to it // via the static-server. It should fail to connect with the // static-server pod because of intentions. - assertNoConnectionAndAddIntention(t, consulClient, nsK8SOptions, testNamespace, testNamespace) + logger.Log(t, "testing intentions prevent connections through the terminating gateway") + k8s.CheckStaticServerConnectionFailing(t, nsK8SOptions, staticClientName, staticServerLocalAddress) + + logger.Log(t, "adding intentions to allow traffic from client ==> server") + addIntention(t, consulClient, testNamespace, staticClientName, testNamespace, staticServerName) } // Test that we can make a call to the terminating gateway. logger.Log(t, "trying calls to terminating gateway") - k8s.CheckStaticServerConnectionSuccessful(t, nsK8SOptions, StaticClientName, "http://localhost:1234") + k8s.CheckStaticServerConnectionSuccessful(t, nsK8SOptions, staticClientName, staticServerLocalAddress) }) } } @@ -207,13 +211,13 @@ func TestTerminatingGatewayNamespaceMirroring(t *testing.T) { // If ACLs are enabled we need to update the role of the terminating gateway // with service:write permissions to the static-server service - // so that it can can request Connect certificates for it. + // so that it can request Connect certificates for it. if c.secure { updateTerminatingGatewayRole(t, consulClient, fmt.Sprintf(staticServerPolicyRulesNamespace, testNamespace)) } // Create the config entry for the terminating gateway - createTerminatingGatewayConfigEntry(t, consulClient, "", testNamespace) + createTerminatingGatewayConfigEntry(t, consulClient, "", testNamespace, staticServerName) // Deploy the static client logger.Log(t, "deploying static client") @@ -224,12 +228,16 @@ func TestTerminatingGatewayNamespaceMirroring(t *testing.T) { // With the terminating gateway up, we test that we can make a call to it // via the static-server. It should fail to connect with the // static-server pod because of intentions. - assertNoConnectionAndAddIntention(t, consulClient, ns2K8SOptions, StaticClientNamespace, testNamespace) + logger.Log(t, "testing intentions prevent connections through the terminating gateway") + k8s.CheckStaticServerConnectionFailing(t, ns2K8SOptions, staticClientName, staticServerLocalAddress) + + logger.Log(t, "adding intentions to allow traffic from client ==> server") + addIntention(t, consulClient, StaticClientNamespace, staticClientName, testNamespace, staticServerName) } // Test that we can make a call to the terminating gateway logger.Log(t, "trying calls to terminating gateway") - k8s.CheckStaticServerConnectionSuccessful(t, ns2K8SOptions, StaticClientName, "http://localhost:1234") + k8s.CheckStaticServerConnectionSuccessful(t, ns2K8SOptions, staticClientName, staticServerLocalAddress) }) } } diff --git a/acceptance/tests/terminating-gateway/terminating_gateway_test.go b/acceptance/tests/terminating-gateway/terminating_gateway_test.go index 411bf9074e..8facd30f53 100644 --- a/acceptance/tests/terminating-gateway/terminating_gateway_test.go +++ b/acceptance/tests/terminating-gateway/terminating_gateway_test.go @@ -3,10 +3,8 @@ package terminatinggateway import ( "fmt" "strconv" - "strings" "testing" - terratestk8s "github.com/gruntwork-io/terratest/modules/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/consul" "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" @@ -15,9 +13,6 @@ import ( "github.com/stretchr/testify/require" ) -const StaticClientName = "static-client" -const staticServerName = "static-server" - // Test that terminating gateways work in a default and secure installations. func TestTerminatingGateway(t *testing.T) { cases := []struct { @@ -71,13 +66,13 @@ func TestTerminatingGateway(t *testing.T) { // If ACLs are enabled we need to update the role of the terminating gateway // with service:write permissions to the static-server service - // so that it can can request Connect certificates for it. + // so that it can request Connect certificates for it. if c.secure { updateTerminatingGatewayRole(t, consulClient, staticServerPolicyRules) } // Create the config entry for the terminating gateway. - createTerminatingGatewayConfigEntry(t, consulClient, "", "") + createTerminatingGatewayConfigEntry(t, consulClient, "", "", staticServerName) // Deploy the static client logger.Log(t, "deploying static client") @@ -88,12 +83,16 @@ func TestTerminatingGateway(t *testing.T) { // With the terminating gateway up, we test that we can make a call to it // via the static-server. It should fail to connect with the // static-server pod because of intentions. - assertNoConnectionAndAddIntention(t, consulClient, ctx.KubectlOptions(t), "", "") + logger.Log(t, "testing intentions prevent connections through the terminating gateway") + k8s.CheckStaticServerConnectionFailing(t, ctx.KubectlOptions(t), staticClientName, staticServerLocalAddress) + + logger.Log(t, "adding intentions to allow traffic from client ==> server") + addIntention(t, consulClient, "", staticClientName, "", staticServerName) } // Test that we can make a call to the terminating gateway. logger.Log(t, "trying calls to terminating gateway") - k8s.CheckStaticServerConnectionSuccessful(t, ctx.KubectlOptions(t), StaticClientName, "http://localhost:1234") + k8s.CheckStaticServerConnectionSuccessful(t, ctx.KubectlOptions(t), staticClientName, staticServerLocalAddress) }) } } @@ -132,79 +131,3 @@ func registerExternalService(t *testing.T, consulClient *api.Client, namespace s }, nil) require.NoError(t, err) } - -func updateTerminatingGatewayRole(t *testing.T, consulClient *api.Client, rules string) { - t.Helper() - - logger.Log(t, "creating a write policy for the static-server") - _, _, err := consulClient.ACL().PolicyCreate(&api.ACLPolicy{ - Name: "static-server-write-policy", - Rules: rules, - }, nil) - require.NoError(t, err) - - logger.Log(t, "getting the terminating gateway role") - roles, _, err := consulClient.ACL().RoleList(nil) - require.NoError(t, err) - terminatingGatewayRoleID := "" - for _, role := range roles { - if strings.Contains(role.Name, "terminating-gateway") { - terminatingGatewayRoleID = role.ID - break - } - } - - logger.Log(t, "update role with policy") - termGwRole, _, err := consulClient.ACL().RoleRead(terminatingGatewayRoleID, nil) - require.NoError(t, err) - termGwRole.Policies = append(termGwRole.Policies, &api.ACLTokenPolicyLink{Name: "static-server-write-policy"}) - _, _, err = consulClient.ACL().RoleUpdate(termGwRole, nil) - require.NoError(t, err) -} - -func createTerminatingGatewayConfigEntry(t *testing.T, consulClient *api.Client, gwNamespace, serviceNamespace string) { - t.Helper() - - logger.Log(t, "creating config entry") - - if serviceNamespace != "" { - logger.Logf(t, "creating the %s namespace in Consul", serviceNamespace) - _, _, err := consulClient.Namespaces().Create(&api.Namespace{ - Name: serviceNamespace, - }, nil) - require.NoError(t, err) - } - - configEntry := &api.TerminatingGatewayConfigEntry{ - Kind: api.TerminatingGateway, - Name: "terminating-gateway", - Namespace: gwNamespace, - Services: []api.LinkedService{{Name: staticServerName, Namespace: serviceNamespace}}, - } - - created, _, err := consulClient.ConfigEntries().Set(configEntry, nil) - require.NoError(t, err) - require.True(t, created, "failed to create config entry") -} - -func assertNoConnectionAndAddIntention(t *testing.T, consulClient *api.Client, k8sOptions *terratestk8s.KubectlOptions, sourceNS, destinationNS string) { - t.Helper() - - logger.Log(t, "testing intentions prevent connections through the terminating gateway") - k8s.CheckStaticServerConnectionFailing(t, k8sOptions, StaticClientName, "http://localhost:1234") - - logger.Log(t, "creating static-client => static-server intention") - _, _, err := consulClient.ConfigEntries().Set(&api.ServiceIntentionsConfigEntry{ - Kind: api.ServiceIntentions, - Name: staticServerName, - Namespace: destinationNS, - Sources: []*api.SourceIntention{ - { - Name: StaticClientName, - Namespace: sourceNS, - Action: api.IntentionActionAllow, - }, - }, - }, nil) - require.NoError(t, err) -} From 2c171ad8e86b7267fb8f2eb54ada69eaae50550b Mon Sep 17 00:00:00 2001 From: David Yu Date: Mon, 22 Aug 2022 11:30:05 -0700 Subject: [PATCH 095/235] README: Update to README regarding upcoming breaking changes (#1439) * README: Update to README regarding upcoming breaking changes --- README.md | 3 +++ charts/consul/README.md | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/README.md b/README.md index ae543ca226..de65faff15 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,9 @@ **We're looking for feedback on how folks are using Consul on Kubernetes. Please fill out our brief [survey](https://hashicorp.sjc1.qualtrics.com/jfe/form/SV_4MANbw1BUku7YhL)!** + +> **Warning** +> Please read the following issue to learn more about upcoming breaking changes that will be implemented by Q4 2022 for the default deployment of Consul on Kubernetes: [Enabling of service mesh by default and disabling of node-level client agents from Consul Service Mesh on Kubernetes and Catalog Sync](https://github.com/hashicorp/consul-k8s/issues/1438) ## Overview diff --git a/charts/consul/README.md b/charts/consul/README.md index 2bc897fc63..36e104bb15 100644 --- a/charts/consul/README.md +++ b/charts/consul/README.md @@ -3,6 +3,10 @@ --- **We're looking for feedback on how folks are using Consul on Kubernetes. Please fill out our brief [survey](https://hashicorp.sjc1.qualtrics.com/jfe/form/SV_4MANbw1BUku7YhL)!** + + + > **Warning** + > Please read the following issue to learn more about upcoming breaking changes that will be implemented by Q4 2022 for the default deployment of Consul on Kubernetes: [Enabling of service mesh by default and disabling of node-level client agents from Consul Service Mesh on Kubernetes and Catalog Sync](https://github.com/hashicorp/consul-k8s/issues/1438) ## Overview From 2bb85a70967e06d721998fb5bddbe4d75373dd0a Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Tue, 23 Aug 2022 13:33:41 -0400 Subject: [PATCH 096/235] Fix some smaller Envoy Debugging bugs. (#1412) * Don't show 'non-domain' FQDNs * Show message about no pods being found * Fix tests for not showing "non-domain" FQDNs * Add a warning if field filter and table filter combo is wacky * Fix linting issue * Re-add newline in list command * Return nil from initKubernetes * Change out to exitCode Co-authored-by: Iryna Shustava * Use contains instead of regex * Include FQDNs without periods as FQDNs * Expand the filtering tests * Test multiple warnings properly * Add changelog improvements --- CHANGELOG.md | 6 + cli/cmd/proxy/list/command.go | 39 +- cli/cmd/proxy/list/command_test.go | 32 ++ cli/cmd/proxy/read/command.go | 32 ++ cli/cmd/proxy/read/command_test.go | 144 ++++- cli/cmd/proxy/read/config.go | 2 +- cli/cmd/proxy/read/config_test.go | 151 +----- cli/cmd/proxy/read/test_clusters.json | 655 +++++++++++++---------- cli/cmd/proxy/read/test_config_dump.json | 254 ++------- 9 files changed, 637 insertions(+), 678 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 650fa52068..cd40a75e77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ ## UNRELEASED +IMPROVEMENTS: +* CLI: + * Display clusters by their short names rather than FQDNs for the `proxy read` command. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] + * Display a message when `proxy list` returns no results. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] + * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] + ## 0.47.1 (August 12, 2022) BUG FIXES: diff --git a/cli/cmd/proxy/list/command.go b/cli/cmd/proxy/list/command.go index 9d62351857..780a376a0f 100644 --- a/cli/cmd/proxy/list/command.go +++ b/cli/cmd/proxy/list/command.go @@ -21,7 +21,6 @@ type ListCommand struct { *common.BaseCommand kubernetes kubernetes.Interface - namespace string set *flag.Sets @@ -129,8 +128,7 @@ func (c *ListCommand) validateFlags() error { return nil } -// initKubernetes initializes the Kubernetes client and sets the namespace based -// on the user-provided arguments. +// initKubernetes initializes the Kubernetes client. func (c *ListCommand) initKubernetes() error { settings := helmCLI.New() @@ -150,15 +148,19 @@ func (c *ListCommand) initKubernetes() error { return fmt.Errorf("error creating Kubernetes client %v", err) } + return nil +} + +func (c *ListCommand) namespace() string { + settings := helmCLI.New() + if c.flagAllNamespaces { - c.namespace = "" // An empty namespace means all namespaces. + return "" // An empty namespace means all namespaces. } else if c.flagNamespace != "" { - c.namespace = c.flagNamespace + return c.flagNamespace } else { - c.namespace = settings.Namespace() + return settings.Namespace() } - - return err } // fetchPods fetches all pods in flagNamespace which run Consul proxies. @@ -166,7 +168,7 @@ func (c *ListCommand) fetchPods() ([]v1.Pod, error) { var pods []v1.Pod // Fetch all pods in the namespace with labels matching the gateway component names. - gatewaypods, err := c.kubernetes.CoreV1().Pods(c.namespace).List(c.Ctx, metav1.ListOptions{ + gatewaypods, err := c.kubernetes.CoreV1().Pods(c.namespace()).List(c.Ctx, metav1.ListOptions{ LabelSelector: "component in (ingress-gateway, mesh-gateway, terminating-gateway), chart=consul-helm", }) if err != nil { @@ -175,7 +177,7 @@ func (c *ListCommand) fetchPods() ([]v1.Pod, error) { pods = append(pods, gatewaypods.Items...) // Fetch all pods in the namespace with a label indicating they are an API gateway. - apigatewaypods, err := c.kubernetes.CoreV1().Pods(c.namespace).List(c.Ctx, metav1.ListOptions{ + apigatewaypods, err := c.kubernetes.CoreV1().Pods(c.namespace()).List(c.Ctx, metav1.ListOptions{ LabelSelector: "api-gateway.consul.hashicorp.com/managed=true", }) if err != nil { @@ -184,7 +186,7 @@ func (c *ListCommand) fetchPods() ([]v1.Pod, error) { pods = append(pods, apigatewaypods.Items...) // Fetch all pods in the namespace with a label indicating they are a service networked by Consul. - sidecarpods, err := c.kubernetes.CoreV1().Pods(c.namespace).List(c.Ctx, metav1.ListOptions{ + sidecarpods, err := c.kubernetes.CoreV1().Pods(c.namespace()).List(c.Ctx, metav1.ListOptions{ LabelSelector: "consul.hashicorp.com/connect-inject-status=injected", }) if err != nil { @@ -197,10 +199,19 @@ func (c *ListCommand) fetchPods() ([]v1.Pod, error) { // output prints a table of pods to the terminal. func (c *ListCommand) output(pods []v1.Pod) { + if len(pods) == 0 { + if c.flagAllNamespaces { + c.UI.Output("No proxies found across all namespaces.") + } else { + c.UI.Output("No proxies found in %s namespace.", c.namespace()) + } + return + } + if c.flagAllNamespaces { - c.UI.Output("Namespace: All Namespaces\n") - } else if c.namespace != "" { - c.UI.Output("Namespace: %s\n", c.namespace) + c.UI.Output("Namespace: all namespaces\n") + } else { + c.UI.Output("Namespace: %s\n", c.namespace()) } var tbl *terminal.Table diff --git a/cli/cmd/proxy/list/command_test.go b/cli/cmd/proxy/list/command_test.go index df6aaf024b..a29c851391 100644 --- a/cli/cmd/proxy/list/command_test.go +++ b/cli/cmd/proxy/list/command_test.go @@ -209,6 +209,9 @@ func TestFetchPods(t *testing.T) { c := setupCommand(new(bytes.Buffer)) c.kubernetes = fake.NewSimpleClientset(&v1.PodList{Items: tc.pods}) c.flagNamespace = tc.namespace + if tc.namespace == "" { + c.flagAllNamespaces = true + } pods, err := c.fetchPods() @@ -308,6 +311,35 @@ func TestListCommandOutput(t *testing.T) { } } +func TestNoPodsFound(t *testing.T) { + cases := map[string]struct { + args []string + expected string + }{ + "Default namespace": { + []string{"-n", "default"}, + "No proxies found in default namespace.", + }, + "All namespaces": { + []string{"-A"}, + "No proxies found across all namespaces.", + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + buf := new(bytes.Buffer) + c := setupCommand(buf) + c.kubernetes = fake.NewSimpleClientset() + + exitCode := c.Run(tc.args) + require.Equal(t, 0, exitCode) + + require.Contains(t, buf.String(), tc.expected) + }) + } +} + func setupCommand(buf io.Writer) *ListCommand { // Log at a test level to standard out. log := hclog.New(&hclog.LoggerOptions{ diff --git a/cli/cmd/proxy/read/command.go b/cli/cmd/proxy/read/command.go index 31e1d20892..235a17f4a5 100644 --- a/cli/cmd/proxy/read/command.go +++ b/cli/cmd/proxy/read/command.go @@ -327,6 +327,34 @@ func (c *ReadCommand) shouldPrintTable(table bool) bool { return !(c.flagClusters || c.flagEndpoints || c.flagListeners || c.flagRoutes || c.flagSecrets) } +// filterWarnings checks if the user has passed in a combination of field and +// table filters where the field in question is not present on the table and +// returns a warning. +// For example, if the user passes "-fqdn default -endpoints", a warning will +// be printed saying "The filter `-fqdn default` does not apply to the tables displayed.". +func (c *ReadCommand) filterWarnings() []string { + var warnings []string + + // No table filters passed. Return early. + if !(c.flagClusters || c.flagEndpoints || c.flagListeners || c.flagRoutes || c.flagSecrets) { + return warnings + } + + if c.flagFQDN != "" && !c.flagClusters { + warnings = append(warnings, fmt.Sprintf("The filter `-fqdn %s` does not apply to the tables displayed.", c.flagFQDN)) + } + + if c.flagPort != -1 && !(c.flagClusters || c.flagEndpoints || c.flagListeners) { + warnings = append(warnings, fmt.Sprintf("The filter `-port %d` does not apply to the tables displayed.", c.flagPort)) + } + + if c.flagAddress != "" && !(c.flagClusters || c.flagEndpoints || c.flagListeners) { + warnings = append(warnings, fmt.Sprintf("The filter `-address %s` does not apply to the tables displayed.", c.flagAddress)) + } + + return warnings +} + func (c *ReadCommand) outputTables(configs map[string]*EnvoyConfig) error { if c.flagFQDN != "" || c.flagAddress != "" || c.flagPort != -1 { c.UI.Output("Filters applied", terminal.WithHeaderStyle()) @@ -341,6 +369,10 @@ func (c *ReadCommand) outputTables(configs map[string]*EnvoyConfig) error { c.UI.Output(fmt.Sprintf("Endpoint addresses with port number: %d", c.flagPort), terminal.WithInfoStyle()) } + for _, warning := range c.filterWarnings() { + c.UI.Output(warning, terminal.WithWarningStyle()) + } + c.UI.Output("") } diff --git a/cli/cmd/proxy/read/command_test.go b/cli/cmd/proxy/read/command_test.go index 5295484be8..48f5aab6a2 100644 --- a/cli/cmd/proxy/read/command_test.go +++ b/cli/cmd/proxy/read/command_test.go @@ -61,44 +61,38 @@ func TestReadCommandOutput(t *testing.T) { // These regular expressions must be present in the output. expectedHeader := fmt.Sprintf("Envoy configuration for %s in namespace default:", podName) expected := map[string][]string{ - "-clusters": {"==> Clusters \\(6\\)", + "-clusters": {"==> Clusters \\(5\\)", "Name.*FQDN.*Endpoints.*Type.*Last Updated", - "local_agent.*local_agent.*192\\.168\\.79\\.187:8502.*STATIC.*2022-05-13T04:22:39\\.553Z", - "local_app.*local_app.*127\\.0\\.0\\.1:8080.*STATIC.*2022-05-13T04:22:39\\.655Z", - "client.*client\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS.*2022-06-09T00:39:12\\.948Z", - "frontend.*frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS.*2022-06-09T00:39:12\\.855Z", - "original-destination.*original-destination.*ORIGINAL_DST.*2022-05-13T04:22:39.743Z", - "server.*server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul.*EDS.*2022-06-09T00:39:12\\.754Z"}, - - "-endpoints": {"==> Endpoints \\(9\\)", + "local_agent.*192\\.168\\.79\\.187:8502.*STATIC.*2022-05-13T04:22:39\\.553Z", + "local_app.*127\\.0\\.0\\.1:8080.*STATIC.*2022-05-13T04:22:39\\.655Z", + "client.*client\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul.*EDS", + "frontend.*frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul", + "original-destination.*ORIGINAL_DST"}, + + "-endpoints": {"==> Endpoints \\(6\\)", "Address:Port.*Cluster.*Weight.*Status", "192.168.79.187:8502.*local_agent.*1.00.*HEALTHY", "127.0.0.1:8080.*local_app.*1.00.*HEALTHY", - "192.168.31.201:20000.*1.00.*HEALTHY", - "192.168.47.235:20000.*1.00.*HEALTHY", - "192.168.71.254:20000.*1.00.*HEALTHY", - "192.168.63.120:20000.*1.00.*HEALTHY", - "192.168.18.110:20000.*1.00.*HEALTHY", - "192.168.52.101:20000.*1.00.*HEALTHY", - "192.168.65.131:20000.*1.00.*HEALTHY"}, + "192.168.18.110:20000.*client.*1.00.*HEALTHY", + "192.168.52.101:20000.*client.*1.00.*HEALTHY", + "192.168.65.131:20000.*client.*1.00.*HEALTHY", + "192.168.63.120:20000.*frontend.*1.00.*HEALTHY"}, "-listeners": {"==> Listeners \\(2\\)", "Name.*Address:Port.*Direction.*Filter Chain Match.*Filters.*Last Updated", - "public_listener.*192\\.168\\.69\\.179:20000.*INBOUND.*Any.*\\* to local_app/.*2022-06-09T00:39:27\\.668Z", - "outbound_listener.*127.0.0.1:15001.*OUTBOUND.*10\\.100\\.134\\.173/32, 240\\.0\\.0\\.3/32.*to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul.*2022-05-24T17:41:59\\.079Z", - "10\\.100\\.254\\.176/32, 240\\.0\\.0\\.4/32.*\\* to server\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul/", - "10\\.100\\.31\\.2/32, 240\\.0\\.0\\.2/32.*to frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul", + "public_listener.*192\\.168\\.69\\.179:20000.*INBOUND.*Any.*\\* to local_app/", + "outbound_listener.*127.0.0.1:15001.*OUTBOUND.*10\\.100\\.134\\.173/32, 240\\.0\\.0\\.3/32.*to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + "10\\.100\\.31\\.2/32, 240\\.0\\.0\\.5/32.*to frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul", "Any.*to original-destination"}, - "-routes": {"==> Routes \\(2\\)", + "-routes": {"==> Routes \\(1\\)", "Name.*Destination Cluster.*Last Updated", - "public_listener.*local_app/.*2022-06-09T00:39:27.667Z", - "server.*server\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul/.*2022-05-24T17:41:59\\.078Z"}, + "public_listener.*local_app/"}, "-secrets": {"==> Secrets \\(2\\)", "Name.*Type.*Last Updated", - "default.*Dynamic Active.*2022-05-24T17:41:59.078Z", - "ROOTCA.*Dynamic Warming.*2022-03-15T05:14:22.868Z"}, + "default.*Dynamic Active", + "ROOTCA.*Dynamic Warming"}, } cases := map[string][]string{ @@ -146,6 +140,106 @@ func TestReadCommandOutput(t *testing.T) { } } +// TestFilterWarnings ensures that a warning is printed if the user applies a +// field filter (e.g. -fqdn default) and a table filter (e.g. -secrets) where +// the former does not affect the output of the latter. +func TestFilterWarnings(t *testing.T) { + podName := "fakePod" + cases := map[string]struct { + input []string + warnings []string + }{ + "fully qualified domain name doesn't apply to listeners": { + input: []string{"-fqdn", "default", "-listeners"}, + warnings: []string{"The filter `-fqdn default` does not apply to the tables displayed."}, + }, + "fully qualified domain name doesn't apply to routes": { + input: []string{"-fqdn", "default", "-routes"}, + warnings: []string{"The filter `-fqdn default` does not apply to the tables displayed."}, + }, + "fully qualified domain name doesn't apply to endpoints": { + input: []string{"-fqdn", "default", "-endpoints"}, + warnings: []string{"The filter `-fqdn default` does not apply to the tables displayed."}, + }, + "fully qualified domain name doesn't apply to secrets": { + input: []string{"-fqdn", "default", "-secrets"}, + warnings: []string{"The filter `-fqdn default` does not apply to the tables displayed."}, + }, + "fully qualified domain name doesn't apply to endpoints or listeners": { + input: []string{"-fqdn", "default", "-endpoints", "-listeners"}, + warnings: []string{"The filter `-fqdn default` does not apply to the tables displayed."}, + }, + "fully qualified domain name doesn't apply to listeners, routes, endpoints, or secrets": { + input: []string{"-fqdn", "default", "-listeners", "-routes", "-endpoints", "-secrets"}, + warnings: []string{"The filter `-fqdn default` does not apply to the tables displayed."}, + }, + "port doesn't apply to routes": { + input: []string{"-port", "8080", "-routes"}, + warnings: []string{"The filter `-port 8080` does not apply to the tables displayed."}, + }, + "port doesn't apply to secrets": { + input: []string{"-port", "8080", "-secrets"}, + warnings: []string{"The filter `-port 8080` does not apply to the tables displayed."}, + }, + "port doesn't apply to secrets or routes": { + input: []string{"-port", "8080", "-secrets", "-routes"}, + warnings: []string{"The filter `-port 8080` does not apply to the tables displayed."}, + }, + "address does not apply to routes": { + input: []string{"-address", "127.0.0.1", "-routes"}, + warnings: []string{"The filter `-address 127.0.0.1` does not apply to the tables displayed."}, + }, + "address does not apply to secrets": { + input: []string{"-address", "127.0.0.1", "-secrets"}, + warnings: []string{"The filter `-address 127.0.0.1` does not apply to the tables displayed."}, + }, + "warn address and port": { + input: []string{"-address", "127.0.0.1", "-port", "8080", "-secrets"}, + warnings: []string{ + "The filter `-address 127.0.0.1` does not apply to the tables displayed.", + "The filter `-port 8080` does not apply to the tables displayed.", + }, + }, + "warn fqdn, address, and port": { + input: []string{"-fqdn", "default", "-address", "127.0.0.1", "-port", "8080", "-secrets"}, + warnings: []string{ + "The filter `-fqdn default` does not apply to the tables displayed.", + "The filter `-address 127.0.0.1` does not apply to the tables displayed.", + "The filter `-port 8080` does not apply to the tables displayed.", + }, + }, + "no warning produced (happy case)": { + input: []string{"-fqdn", "default", "-clusters"}, + warnings: []string{}, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + fakePod := v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: podName, + Namespace: "default", + }, + } + + buf := new(bytes.Buffer) + c := setupCommand(buf) + c.kubernetes = fake.NewSimpleClientset(&v1.PodList{Items: []v1.Pod{fakePod}}) + c.fetchConfig = func(context.Context, common.PortForwarder) (*EnvoyConfig, error) { + return testEnvoyConfig, nil + } + + exitCode := c.Run(append([]string{podName}, tc.input...)) + require.Equal(t, 0, exitCode) // This shouldn't error out, just warn the user. + + for _, warning := range tc.warnings { + require.Contains(t, buf.String(), warning) + } + }) + } +} + func setupCommand(buf io.Writer) *ReadCommand { // Log at a test level to standard out. log := hclog.New(&hclog.LoggerOptions{ diff --git a/cli/cmd/proxy/read/config.go b/cli/cmd/proxy/read/config.go index cc3fa8d7e5..a3ec904146 100644 --- a/cli/cmd/proxy/read/config.go +++ b/cli/cmd/proxy/read/config.go @@ -257,7 +257,7 @@ func parseEndpoints(rawCfg map[string]interface{}, endpointMapping map[string]st endpoints = append(endpoints, Endpoint{ Address: address, - Cluster: cluster, + Cluster: strings.Split(cluster, ".")[0], Weight: lbEndpoint.LoadBalancingWeight, Status: lbEndpoint.HealthStatus, }) diff --git a/cli/cmd/proxy/read/config_test.go b/cli/cmd/proxy/read/config_test.go index cce3c4c12a..a32451a3c2 100644 --- a/cli/cmd/proxy/read/config_test.go +++ b/cli/cmd/proxy/read/config_test.go @@ -102,148 +102,33 @@ func rawEnvoyConfig(t *testing.T) []byte { // testEnvoyConfig is what we expect the config at `test_config_dump.json` to be. var testEnvoyConfig = &EnvoyConfig{ Clusters: []Cluster{ - { - Name: "local_agent", - FullyQualifiedDomainName: "local_agent", - Endpoints: []string{"192.168.79.187:8502", "172.18.0.2:8502"}, - Type: "STATIC", - LastUpdated: "2022-05-13T04:22:39.553Z", - }, - { - Name: "client", - FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", - Endpoints: []string{}, - Type: "EDS", - LastUpdated: "2022-06-09T00:39:12.948Z", - }, - { - Name: "frontend", - FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", - Endpoints: []string{}, - Type: "EDS", - LastUpdated: "2022-06-09T00:39:12.855Z", - }, - { - Name: "local_app", - FullyQualifiedDomainName: "local_app", - Endpoints: []string{"127.0.0.1:8080", "127.0.0.1:0"}, - Type: "STATIC", - LastUpdated: "2022-05-13T04:22:39.655Z", - }, - { - Name: "original-destination", - FullyQualifiedDomainName: "original-destination", - Endpoints: []string{}, - Type: "ORIGINAL_DST", - LastUpdated: "2022-05-13T04:22:39.743Z", - }, - { - Name: "server", - FullyQualifiedDomainName: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", - Endpoints: []string{}, - Type: "EDS", - LastUpdated: "2022-06-09T00:39:12.754Z", - }, + {Name: "local_agent", FullyQualifiedDomainName: "local_agent", Endpoints: []string{"192.168.79.187:8502"}, Type: "STATIC", LastUpdated: "2022-05-13T04:22:39.553Z"}, + {Name: "client", FullyQualifiedDomainName: "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", Endpoints: []string{"192.168.18.110:20000", "192.168.52.101:20000", "192.168.65.131:20000"}, Type: "EDS", LastUpdated: "2022-08-10T12:30:32.326Z"}, + {Name: "frontend", FullyQualifiedDomainName: "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", Endpoints: []string{"192.168.63.120:20000"}, Type: "EDS", LastUpdated: "2022-08-10T12:30:32.233Z"}, + {Name: "local_app", FullyQualifiedDomainName: "local_app", Endpoints: []string{"127.0.0.1:8080"}, Type: "STATIC", LastUpdated: "2022-05-13T04:22:39.655Z"}, + {Name: "original-destination", FullyQualifiedDomainName: "original-destination", Endpoints: []string{}, Type: "ORIGINAL_DST", LastUpdated: "2022-05-13T04:22:39.743Z"}, }, Endpoints: []Endpoint{ - { - Address: "192.168.79.187:8502", - Cluster: "local_agent", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "127.0.0.1:8080", - Cluster: "local_app", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.31.201:20000", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.47.235:20000", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.71.254:20000", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.63.120:20000", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.18.110:20000", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.52.101:20000", - Weight: 1, - Status: "HEALTHY", - }, - { - Address: "192.168.65.131:20000", - Weight: 1, - Status: "HEALTHY", - }, + {Address: "192.168.79.187:8502", Cluster: "local_agent", Weight: 1, Status: "HEALTHY"}, + {Address: "192.168.18.110:20000", Cluster: "client", Weight: 1, Status: "HEALTHY"}, + {Address: "192.168.52.101:20000", Cluster: "client", Weight: 1, Status: "HEALTHY"}, + {Address: "192.168.65.131:20000", Cluster: "client", Weight: 1, Status: "HEALTHY"}, + {Address: "192.168.63.120:20000", Cluster: "frontend", Weight: 1, Status: "HEALTHY"}, + {Address: "127.0.0.1:8080", Cluster: "local_app", Weight: 1, Status: "HEALTHY"}, }, Listeners: []Listener{ - { - Name: "public_listener", - Address: "192.168.69.179:20000", - FilterChain: []FilterChain{ - { - FilterChainMatch: "Any", - Filters: []string{"* to local_app/"}, - }, - }, - Direction: "INBOUND", - LastUpdated: "2022-06-09T00:39:27.668Z", - }, - { - Name: "outbound_listener", - Address: "127.0.0.1:15001", - FilterChain: []FilterChain{ - { - FilterChainMatch: "10.100.134.173/32, 240.0.0.3/32", - Filters: []string{"to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, - }, - { - FilterChainMatch: "10.100.254.176/32, 240.0.0.4/32", - Filters: []string{"* to server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/"}, - }, - { - FilterChainMatch: "10.100.31.2/32, 240.0.0.2/32", - Filters: []string{ - "to frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", - }, - }, - { - FilterChainMatch: "Any", - Filters: []string{"to original-destination"}, - }, - }, - Direction: "OUTBOUND", - LastUpdated: "2022-05-24T17:41:59.079Z", - }, + {Name: "public_listener", Address: "192.168.69.179:20000", FilterChain: []FilterChain{{Filters: []string{"* to local_app/"}, FilterChainMatch: "Any"}}, Direction: "INBOUND", LastUpdated: "2022-08-10T12:30:47.142Z"}, + {Name: "outbound_listener", Address: "127.0.0.1:15001", FilterChain: []FilterChain{ + {Filters: []string{"to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, FilterChainMatch: "10.100.134.173/32, 240.0.0.3/32"}, + {Filters: []string{"to frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, FilterChainMatch: "10.100.31.2/32, 240.0.0.5/32"}, + {Filters: []string{"to original-destination"}, FilterChainMatch: "Any"}, + }, Direction: "OUTBOUND", LastUpdated: "2022-07-18T15:31:03.246Z"}, }, Routes: []Route{ { Name: "public_listener", DestinationCluster: "local_app/", - LastUpdated: "2022-06-09T00:39:27.667Z", - }, - { - Name: "server", - DestinationCluster: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/", - LastUpdated: "2022-05-24T17:41:59.078Z", + LastUpdated: "2022-08-10T12:30:47.141Z", }, }, Secrets: []Secret{ diff --git a/cli/cmd/proxy/read/test_clusters.json b/cli/cmd/proxy/read/test_clusters.json index 55a4c244b2..83b52f3162 100644 --- a/cli/cmd/proxy/read/test_clusters.json +++ b/cli/cmd/proxy/read/test_clusters.json @@ -1,302 +1,373 @@ { - "cluster_statuses": [ + "cluster_statuses": [ + { + "name": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + "added_via_api": true, + "host_statuses": [ { - "name": "local_app", - "added_via_api": true, - "host_statuses": [ - { - "address": { - "socket_address": { - "address": "127.0.0.1", - "port_value": 0 - } - }, - "stats": [ - { - "value": "6", - "name": "cx_connect_fail" - }, - { - "value": "38", - "name": "cx_total" - }, - { - "name": "rq_error" - }, - { - "name": "rq_success" - }, - { - "name": "rq_timeout" - }, - { - "name": "rq_total" - }, - { - "type": "GAUGE", - "name": "cx_active" - }, - { - "type": "GAUGE", - "name": "rq_active" - } - ], - "health_status": { - "eds_health_status": "HEALTHY" - }, - "weight": 1, - "locality": { - - } - } - ], - "circuit_breakers": { - "thresholds": [ - { - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - }, - { - "priority": "HIGH", - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - } - ] - }, - "observability_name": "local_app" + "address": { + "socket_address": { + "address": "192.168.18.110", + "port_value": 20000 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": {} }, { - "name": "self_admin", - "host_statuses": [ - { - "address": { - "socket_address": { - "address": "127.0.0.1", - "port_value": 19000 - } - }, - "stats": [ - { - "name": "cx_connect_fail" - }, - { - "value": "1", - "name": "cx_total" - }, - { - "name": "rq_error" - }, - { - "value": "26", - "name": "rq_success" - }, - { - "name": "rq_timeout" - }, - { - "value": "26", - "name": "rq_total" - }, - { - "type": "GAUGE", - "value": "1", - "name": "cx_active" - }, - { - "type": "GAUGE", - "name": "rq_active" - } - ], - "health_status": { - "eds_health_status": "HEALTHY" - }, - "weight": 1, - "locality": { - - } - } - ], - "circuit_breakers": { - "thresholds": [ - { - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - }, - { - "priority": "HIGH", - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - } - ] - }, - "observability_name": "self_admin" + "address": { + "socket_address": { + "address": "192.168.52.101", + "port_value": 20000 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": {} }, { - "name": "original-destination", - "added_via_api": true, - "circuit_breakers": { - "thresholds": [ - { - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - }, - { - "priority": "HIGH", - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - } - ] - }, - "observability_name": "original-destination" - }, + "address": { + "socket_address": { + "address": "192.168.65.131", + "port_value": 20000 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": {} + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + }, + { + "name": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + "added_via_api": true, + "host_statuses": [ { - "name": "static-server.default.dc1.internal.80d0b664-149b-52fa-c6ae-3dad962bdaa8.consul", - "added_via_api": true, - "host_statuses": [ - { - "address": { - "socket_address": { - "address": "10.244.0.74", - "port_value": 20000 - } - }, - "stats": [ - { - "name": "cx_connect_fail" - }, - { - "name": "cx_total" - }, - { - "name": "rq_error" - }, - { - "name": "rq_success" - }, - { - "name": "rq_timeout" - }, - { - "name": "rq_total" - }, - { - "type": "GAUGE", - "name": "cx_active" - }, - { - "type": "GAUGE", - "name": "rq_active" - } - ], - "health_status": { - "eds_health_status": "HEALTHY" - }, - "weight": 1, - "locality": { - - } - } - ], - "circuit_breakers": { - "thresholds": [ - { - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - }, - { - "priority": "HIGH", - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - } - ] - }, - "observability_name": "static-server.default.dc1.internal.80d0b664-149b-52fa-c6ae-3dad962bdaa8.consul" - }, + "address": { + "socket_address": { + "address": "192.168.63.120", + "port_value": 20000 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": {} + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" + }, + { + "name": "original-destination", + "added_via_api": true, + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "original-destination" + }, + { + "name": "local_app", + "added_via_api": true, + "host_statuses": [ + { + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 8080 + } + }, + "stats": [ + { + "name": "cx_connect_fail" + }, + { + "name": "cx_total" + }, + { + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "name": "rq_total" + }, + { + "type": "GAUGE", + "name": "cx_active" + }, + { + "type": "GAUGE", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": {} + } + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "local_app" + }, + { + "name": "local_agent", + "host_statuses": [ { - "name": "local_agent", - "host_statuses": [ - { - "address": { - "socket_address": { - "address": "172.18.0.2", - "port_value": 8502 - } - }, - "stats": [ - { - "name": "cx_connect_fail" - }, - { - "value": "1", - "name": "cx_total" - }, - { - "name": "rq_error" - }, - { - "name": "rq_success" - }, - { - "name": "rq_timeout" - }, - { - "value": "1", - "name": "rq_total" - }, - { - "type": "GAUGE", - "value": "1", - "name": "cx_active" - }, - { - "type": "GAUGE", - "value": "1", - "name": "rq_active" - } - ], - "health_status": { - "eds_health_status": "HEALTHY" - }, - "weight": 1, - "locality": { - - } - } - ], - "circuit_breakers": { - "thresholds": [ - { - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - }, - { - "priority": "HIGH", - "max_connections": 1024, - "max_pending_requests": 1024, - "max_requests": 1024, - "max_retries": 3 - } - ] - }, - "observability_name": "local_agent" + "address": { + "socket_address": { + "address": "192.168.79.187", + "port_value": 8502 + } + }, + "stats": [ + { + "value": "8", + "name": "cx_connect_fail" + }, + { + "value": "11", + "name": "cx_total" + }, + { + "value": "10", + "name": "rq_error" + }, + { + "name": "rq_success" + }, + { + "name": "rq_timeout" + }, + { + "value": "3", + "name": "rq_total" + }, + { + "type": "GAUGE", + "value": "1", + "name": "cx_active" + }, + { + "type": "GAUGE", + "value": "1", + "name": "rq_active" + } + ], + "health_status": { + "eds_health_status": "HEALTHY" + }, + "weight": 1, + "locality": {} } - ] + ], + "circuit_breakers": { + "thresholds": [ + { + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + }, + { + "priority": "HIGH", + "max_connections": 1024, + "max_pending_requests": 1024, + "max_requests": 1024, + "max_retries": 3 + } + ] + }, + "observability_name": "local_agent" + } + ] } diff --git a/cli/cmd/proxy/read/test_config_dump.json b/cli/cmd/proxy/read/test_config_dump.json index 982f50483d..e66e0e325a 100644 --- a/cli/cmd/proxy/read/test_config_dump.json +++ b/cli/cmd/proxy/read/test_config_dump.json @@ -7,8 +7,8 @@ "id": "backend-658b679b45-d5xlb-backend-sidecar-proxy", "cluster": "backend", "metadata": { - "partition": "default", - "namespace": "default" + "namespace": "default", + "partition": "default" }, "user_agent_name": "envoy", "user_agent_build_version": { @@ -17,10 +17,10 @@ "minor_number": 22 }, "metadata": { - "revision.status": "Clean", "ssl.version": "BoringSSL", - "revision.sha": "dcd329a2e95b54f754b17aceca3f72724294b502", - "build.type": "RELEASE" + "revision.status": "Clean", + "build.type": "RELEASE", + "revision.sha": "dcd329a2e95b54f754b17aceca3f72724294b502" } }, "extensions": [ @@ -1255,7 +1255,7 @@ ], "dynamic_active_clusters": [ { - "version_info": "877646fa9c433fbe25febc99b0725a44ab606d9f5407b76a6b7513edd1ac8af2", + "version_info": "2eee24224b508d5e77766867b5ad793bc4555abce4d3fa564da125617c68e46a", "cluster": { "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", "name": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", @@ -1278,7 +1278,7 @@ "tls_certificates": [ { "certificate_chain": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICGzCCAcKgAwIBAgICATgwCgYIKoZIzj0EAwIwMTEvMC0GA1UEAxMmcHJpLTQ5\neHJxcXo0LmNvbnN1bC5jYS5iYzM4MTVjMi5jb25zdWwwHhcNMjIwODEwMTIyOTMx\nWhcNMjIwODEzMTIyOTMxWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwIK1\nchHdnpY6/q384TYjGoNhuB+rZI0dMYDjc6Zlb6i0wIKDXtGF4mu6pGBZLkTg0Jmi\nWRysYZG0xZXJ3CCCZqOB+jCB9zAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYI\nKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEIIz1546B\nHMv70/ecIGSXuy/0UFErFDl+x6rL2H5Q1HuCMCsGA1UdIwQkMCKAINRa97yb1w51\nVrdMgKGBb1/Evynoboq/c78fLjNVCGiJMGAGA1UdEQEB/wRWMFSGUnNwaWZmZTov\nL2JjMzgxNWMyLTFhMGYtZjNmZi1hMmU5LTIwZDc5MWYwOGQwMC5jb25zdWwvbnMv\nZGVmYXVsdC9kYy9kYzEvc3ZjL2JhY2tlbmQwCgYIKoZIzj0EAwIDRwAwRAIgGAkg\n9NJtR/hMkaBS7cTEn5aoQ6NcmsKdAy7UXHysdkcCIFas15UPc5cSjjpNie/UnFde\nH0bDhbYMCKTZVGj3hvhr\n-----END CERTIFICATE-----\n" }, "private_key": { "inline_string": "[redacted]" @@ -1304,10 +1304,10 @@ }, "alt_stat_name": "client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" }, - "last_updated": "2022-06-09T00:39:12.948Z" + "last_updated": "2022-08-10T12:30:32.326Z" }, { - "version_info": "e0cc5c279829d13f01d2ba3a4d32546c0d3fc65b930bbb0bf66a68ad76e152a0", + "version_info": "70b55eac9f1c87dfb54a56d1624279740ddaa2ab72ce7f0baf024b089c396acc", "cluster": { "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", "name": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", @@ -1330,7 +1330,7 @@ "tls_certificates": [ { "certificate_chain": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICGzCCAcKgAwIBAgICATgwCgYIKoZIzj0EAwIwMTEvMC0GA1UEAxMmcHJpLTQ5\neHJxcXo0LmNvbnN1bC5jYS5iYzM4MTVjMi5jb25zdWwwHhcNMjIwODEwMTIyOTMx\nWhcNMjIwODEzMTIyOTMxWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwIK1\nchHdnpY6/q384TYjGoNhuB+rZI0dMYDjc6Zlb6i0wIKDXtGF4mu6pGBZLkTg0Jmi\nWRysYZG0xZXJ3CCCZqOB+jCB9zAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYI\nKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEIIz1546B\nHMv70/ecIGSXuy/0UFErFDl+x6rL2H5Q1HuCMCsGA1UdIwQkMCKAINRa97yb1w51\nVrdMgKGBb1/Evynoboq/c78fLjNVCGiJMGAGA1UdEQEB/wRWMFSGUnNwaWZmZTov\nL2JjMzgxNWMyLTFhMGYtZjNmZi1hMmU5LTIwZDc5MWYwOGQwMC5jb25zdWwvbnMv\nZGVmYXVsdC9kYy9kYzEvc3ZjL2JhY2tlbmQwCgYIKoZIzj0EAwIDRwAwRAIgGAkg\n9NJtR/hMkaBS7cTEn5aoQ6NcmsKdAy7UXHysdkcCIFas15UPc5cSjjpNie/UnFde\nH0bDhbYMCKTZVGj3hvhr\n-----END CERTIFICATE-----\n" }, "private_key": { "inline_string": "[redacted]" @@ -1356,7 +1356,7 @@ }, "alt_stat_name": "frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" }, - "last_updated": "2022-06-09T00:39:12.855Z" + "last_updated": "2022-08-10T12:30:32.233Z" }, { "version_info": "642b6322013fd3f776d9644ece515db5c4901fe6a87575ab4ff07498ab5faa47", @@ -1397,58 +1397,6 @@ "lb_policy": "CLUSTER_PROVIDED" }, "last_updated": "2022-05-13T04:22:39.743Z" - }, - { - "version_info": "1454ffe616e7abd2b3bec548b88f3a14c0500a94de27f2b3e8e3913e7bfd3275", - "cluster": { - "@type": "type.googleapis.com/envoy.config.cluster.v3.Cluster", - "name": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", - "type": "EDS", - "eds_cluster_config": { - "eds_config": { - "ads": {}, - "resource_api_version": "V3" - } - }, - "connect_timeout": "5s", - "circuit_breakers": {}, - "outlier_detection": {}, - "transport_socket": { - "name": "tls", - "typed_config": { - "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext", - "common_tls_context": { - "tls_params": {}, - "tls_certificates": [ - { - "certificate_chain": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" - }, - "private_key": { - "inline_string": "[redacted]" - } - } - ], - "validation_context": { - "trusted_ca": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIICEDCCAbWgAwIBAgIBBzAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA1MTMwNDE4MDBa\nFw0zMjA1MTAwNDE4MDBaMDExLzAtBgNVBAMTJnByaS00OXhycXF6NC5jb25zdWwu\nY2EuYmMzODE1YzIuY29uc3VsMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwQHp\nkEZUr0LVB1ng/zQMQyEQnID/wN/0+Ve648F3Lz4+S7D/S41EQ1Q9ImrNGIlmJ1b2\ncL9WcsL1A1/Ts8xNSaOBvTCBujAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUw\nAwEB/zApBgNVHQ4EIgQg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkw\nKwYDVR0jBCQwIoAg1Fr3vJvXDnVWt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwPwYD\nVR0RBDgwNoY0c3BpZmZlOi8vYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkx\nZjA4ZDAwLmNvbnN1bDAKBggqhkjOPQQDAgNJADBGAiEAhxIMzmCZT1sjtEKsjHIM\nC//yOo+pXZ62GQk+7rsE9HoCIQCxdLmYFUvOOiIXt4S15tvBpuJ6PdrKNlRTbmLx\nA5z5lQ==\n-----END CERTIFICATE-----\n" - }, - "match_subject_alt_names": [ - { - "exact": "spiffe://bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul/ns/default/dc/dc1/svc/server" - } - ] - } - }, - "sni": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" - } - }, - "common_lb_config": { - "healthy_panic_threshold": {} - }, - "alt_stat_name": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" - }, - "last_updated": "2022-06-09T00:39:12.754Z" } ] }, @@ -1486,35 +1434,6 @@ } ], "dynamic_endpoint_configs": [ - { - "endpoint_config": { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "cluster_name": "local_app", - "endpoints": [ - { - "locality": {}, - "lb_endpoints": [ - { - "endpoint": { - "address": { - "socket_address": { - "address": "127.0.0.1", - "port_value": 8080 - } - }, - "health_check_config": {} - }, - "health_status": "HEALTHY", - "load_balancing_weight": 1 - } - ] - } - ], - "policy": { - "overprovisioning_factor": 140 - } - } - }, { "endpoint_config": { "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", @@ -1526,7 +1445,7 @@ "endpoint": { "address": { "socket_address": { - "address": "192.168.31.201", + "address": "192.168.18.110", "port_value": 20000 } }, @@ -1539,7 +1458,7 @@ "endpoint": { "address": { "socket_address": { - "address": "192.168.47.235", + "address": "192.168.52.101", "port_value": 20000 } }, @@ -1552,7 +1471,7 @@ "endpoint": { "address": { "socket_address": { - "address": "192.168.71.254", + "address": "192.168.65.131", "port_value": 20000 } }, @@ -1600,6 +1519,16 @@ { "endpoint_config": { "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "cluster_name": "original-destination", + "policy": { + "overprovisioning_factor": 140 + } + } + }, + { + "endpoint_config": { + "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", + "cluster_name": "local_app", "endpoints": [ { "locality": {}, @@ -1608,34 +1537,8 @@ "endpoint": { "address": { "socket_address": { - "address": "192.168.18.110", - "port_value": 20000 - } - }, - "health_check_config": {} - }, - "health_status": "HEALTHY", - "load_balancing_weight": 1 - }, - { - "endpoint": { - "address": { - "socket_address": { - "address": "192.168.52.101", - "port_value": 20000 - } - }, - "health_check_config": {} - }, - "health_status": "HEALTHY", - "load_balancing_weight": 1 - }, - { - "endpoint": { - "address": { - "socket_address": { - "address": "192.168.65.131", - "port_value": 20000 + "address": "127.0.0.1", + "port_value": 8080 } }, "health_check_config": {} @@ -1650,15 +1553,6 @@ "overprovisioning_factor": 140 } } - }, - { - "endpoint_config": { - "@type": "type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment", - "cluster_name": "original-destination", - "policy": { - "overprovisioning_factor": 140 - } - } } ] }, @@ -1729,6 +1623,16 @@ } } } + }, + { + "authenticated": { + "principal_name": { + "safe_regex": { + "google_re2": {}, + "regex": "^spiffe://[^/]+/ns/default/dc/[^/]+/svc/ingress-gateway$" + } + } + } } ] } @@ -1758,7 +1662,7 @@ "tls_certificates": [ { "certificate_chain": { - "inline_string": "-----BEGIN CERTIFICATE-----\nMIICHDCCAcGgAwIBAgIBWDAKBggqhkjOPQQDAjAxMS8wLQYDVQQDEyZwcmktNDl4\ncnFxejQuY29uc3VsLmNhLmJjMzgxNWMyLmNvbnN1bDAeFw0yMjA2MDkwMDM4MTJa\nFw0yMjA2MTIwMDM4MTJaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARGkJfg\n3Hy48dvsqnsJ7Xmb00ZGzNaGl89++zg3PgppbvXiU+u3oK7qON/pQ3hinsjXnubr\n2y5RRaKjRke+HyTBo4H6MIH3MA4GA1UdDwEB/wQEAwIDuDAdBgNVHSUEFjAUBggr\nBgEFBQcDAgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADApBgNVHQ4EIgQgJK3rY8+n\n0pg4r+1+uIsBl2YqMXGTQdZ45yR8lDILXtEwKwYDVR0jBCQwIoAg1Fr3vJvXDnVW\nt0yAoYFvX8S/Kehuir9zvx8uM1UIaIkwYAYDVR0RAQH/BFYwVIZSc3BpZmZlOi8v\nYmMzODE1YzItMWEwZi1mM2ZmLWEyZTktMjBkNzkxZjA4ZDAwLmNvbnN1bC9ucy9k\nZWZhdWx0L2RjL2RjMS9zdmMvYmFja2VuZDAKBggqhkjOPQQDAgNJADBGAiEAlik6\nBgXf8zAT3cV+ZDEz9d1oApzde8+HLoadXrDimzICIQCCDk3QL/rK5jTv6p0iqkY1\nqUPq56zIQeZ7SHUZe8Wm0A==\n-----END CERTIFICATE-----\n" + "inline_string": "-----BEGIN CERTIFICATE-----\nMIICGzCCAcKgAwIBAgICATgwCgYIKoZIzj0EAwIwMTEvMC0GA1UEAxMmcHJpLTQ5\neHJxcXo0LmNvbnN1bC5jYS5iYzM4MTVjMi5jb25zdWwwHhcNMjIwODEwMTIyOTMx\nWhcNMjIwODEzMTIyOTMxWjAAMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEwIK1\nchHdnpY6/q384TYjGoNhuB+rZI0dMYDjc6Zlb6i0wIKDXtGF4mu6pGBZLkTg0Jmi\nWRysYZG0xZXJ3CCCZqOB+jCB9zAOBgNVHQ8BAf8EBAMCA7gwHQYDVR0lBBYwFAYI\nKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwKQYDVR0OBCIEIIz1546B\nHMv70/ecIGSXuy/0UFErFDl+x6rL2H5Q1HuCMCsGA1UdIwQkMCKAINRa97yb1w51\nVrdMgKGBb1/Evynoboq/c78fLjNVCGiJMGAGA1UdEQEB/wRWMFSGUnNwaWZmZTov\nL2JjMzgxNWMyLTFhMGYtZjNmZi1hMmU5LTIwZDc5MWYwOGQwMC5jb25zdWwvbnMv\nZGVmYXVsdC9kYy9kYzEvc3ZjL2JhY2tlbmQwCgYIKoZIzj0EAwIDRwAwRAIgGAkg\n9NJtR/hMkaBS7cTEn5aoQ6NcmsKdAy7UXHysdkcCIFas15UPc5cSjjpNie/UnFde\nH0bDhbYMCKTZVGj3hvhr\n-----END CERTIFICATE-----\n" }, "private_key": { "inline_string": "[redacted]" @@ -1778,7 +1682,7 @@ ], "traffic_direction": "INBOUND" }, - "last_updated": "2022-06-09T00:39:27.668Z" + "last_updated": "2022-08-10T12:30:47.142Z" } }, { @@ -1819,59 +1723,6 @@ } ] }, - { - "filter_chain_match": { - "prefix_ranges": [ - { - "address_prefix": "10.100.254.176", - "prefix_len": 32 - }, - { - "address_prefix": "240.0.0.4", - "prefix_len": 32 - } - ] - }, - "filters": [ - { - "name": "envoy.filters.network.http_connection_manager", - "typed_config": { - "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", - "stat_prefix": "upstream.server.default.default.dc1", - "route_config": { - "name": "server", - "virtual_hosts": [ - { - "name": "server.default.default.dc1", - "domains": ["*"], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" - } - } - ] - } - ] - }, - "http_filters": [ - { - "name": "envoy.filters.http.router", - "typed_config": { - "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router" - } - } - ], - "tracing": { - "random_sampling": {} - } - } - } - ] - }, { "filter_chain_match": { "prefix_ranges": [ @@ -1880,7 +1731,7 @@ "prefix_len": 32 }, { - "address_prefix": "240.0.0.2", + "address_prefix": "240.0.0.5", "prefix_len": 32 } ] @@ -1919,7 +1770,7 @@ ], "traffic_direction": "OUTBOUND" }, - "last_updated": "2022-05-24T17:41:59.079Z" + "last_updated": "2022-07-18T15:31:03.246Z" } } ] @@ -1951,30 +1802,7 @@ } ] }, - "last_updated": "2022-06-09T00:39:27.667Z" - }, - { - "route_config": { - "@type": "type.googleapis.com/envoy.config.route.v3.RouteConfiguration", - "name": "server", - "virtual_hosts": [ - { - "name": "server.default.default.dc1", - "domains": ["*"], - "routes": [ - { - "match": { - "prefix": "/" - }, - "route": { - "cluster": "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul" - } - } - ] - } - ] - }, - "last_updated": "2022-05-24T17:41:59.078Z" + "last_updated": "2022-08-10T12:30:47.141Z" } ] }, From 13b59265270e7bae11ddda6514468784c0977fd6 Mon Sep 17 00:00:00 2001 From: cskh Date: Tue, 23 Aug 2022 13:40:54 -0400 Subject: [PATCH 097/235] fix: missing MaxInboundConnections in service-defaults CRD (#1437) --- CHANGELOG.md | 3 ++ .../consul/templates/crd-servicedefaults.yaml | 5 ++++ .../api/v1alpha1/servicedefaults_types.go | 29 ++++++++++++------- .../v1alpha1/servicedefaults_types_test.go | 2 ++ .../consul.hashicorp.com_servicedefaults.yaml | 5 ++++ .../controller/configentry_controller_test.go | 4 ++- control-plane/go.mod | 2 +- control-plane/go.sum | 4 +-- 8 files changed, 40 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd40a75e77..cbf53a1f7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## UNRELEASED +FEATURES: +* MaxInboundConnections in service-defaults CRD + * Add support for MaxInboundConnections on the Service Defaults CRD. [[GH-1437](https://github.com/hashicorp/consul-k8s/pull/1437)] IMPROVEMENTS: * CLI: diff --git a/charts/consul/templates/crd-servicedefaults.yaml b/charts/consul/templates/crd-servicedefaults.yaml index ea7720e9a2..f0ba18a616 100644 --- a/charts/consul/templates/crd-servicedefaults.yaml +++ b/charts/consul/templates/crd-servicedefaults.yaml @@ -113,6 +113,11 @@ spec: TLS SNI value to be changed to a non-connect value when federating with an external system. type: string + maxInboundConnections: + description: MaxInboundConnections is the maximum number of concurrent + inbound connections to each service instance. Defaults to 0 (using + consul's default) if not set. + type: integer meshGateway: description: MeshGateway controls the default mesh gateway configuration for this service. diff --git a/control-plane/api/v1alpha1/servicedefaults_types.go b/control-plane/api/v1alpha1/servicedefaults_types.go index 41c855d75c..325b80cefe 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types.go +++ b/control-plane/api/v1alpha1/servicedefaults_types.go @@ -84,6 +84,9 @@ type ServiceDefaultsSpec struct { // mode. Destinations live outside of Consul's catalog, and because of this, they // do not require an artificial node to be created. Destination *ServiceDefaultsDestination `json:"destination,omitempty"` + // MaxInboundConnections is the maximum number of concurrent inbound connections to + // each service instance. Defaults to 0 (using consul's default) if not set. + MaxInboundConnections int `json:"maxInboundConnections,omitempty"` } type Upstreams struct { @@ -245,16 +248,17 @@ func (in *ServiceDefaults) SyncedConditionStatus() corev1.ConditionStatus { // ToConsul converts the entry into it's Consul equivalent struct. func (in *ServiceDefaults) ToConsul(datacenter string) capi.ConfigEntry { return &capi.ServiceConfigEntry{ - Kind: in.ConsulKind(), - Name: in.ConsulName(), - Protocol: in.Spec.Protocol, - MeshGateway: in.Spec.MeshGateway.toConsul(), - Expose: in.Spec.Expose.toConsul(), - ExternalSNI: in.Spec.ExternalSNI, - TransparentProxy: in.Spec.TransparentProxy.toConsul(), - UpstreamConfig: in.Spec.UpstreamConfig.toConsul(), - Destination: in.Spec.Destination.toConsul(), - Meta: meta(datacenter), + Kind: in.ConsulKind(), + Name: in.ConsulName(), + Protocol: in.Spec.Protocol, + MeshGateway: in.Spec.MeshGateway.toConsul(), + Expose: in.Spec.Expose.toConsul(), + ExternalSNI: in.Spec.ExternalSNI, + TransparentProxy: in.Spec.TransparentProxy.toConsul(), + UpstreamConfig: in.Spec.UpstreamConfig.toConsul(), + Destination: in.Spec.Destination.toConsul(), + Meta: meta(datacenter), + MaxInboundConnections: in.Spec.MaxInboundConnections, } } @@ -280,6 +284,11 @@ func (in *ServiceDefaults) Validate(consulMeta common.ConsulMeta) error { if err := in.Spec.Destination.validate(path.Child("destination")); err != nil { allErrs = append(allErrs, err...) } + + if in.Spec.MaxInboundConnections < 0 { + allErrs = append(allErrs, field.Invalid(path.Child("maxinboundconnections"), in.Spec.MaxInboundConnections, "MaxInboundConnections must be > 0")) + } + allErrs = append(allErrs, in.Spec.UpstreamConfig.validate(path.Child("upstreamConfig"), consulMeta.PartitionsEnabled)...) allErrs = append(allErrs, in.Spec.Expose.validate(path.Child("expose"))...) diff --git a/control-plane/api/v1alpha1/servicedefaults_types_test.go b/control-plane/api/v1alpha1/servicedefaults_types_test.go index a19ea556b3..6c15c00c48 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types_test.go +++ b/control-plane/api/v1alpha1/servicedefaults_types_test.go @@ -141,6 +141,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Addresses: []string{"api.google.com"}, Port: 443, }, + MaxInboundConnections: 20, }, }, &capi.ServiceConfigEntry{ @@ -243,6 +244,7 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Addresses: []string{"api.google.com"}, Port: 443, }, + MaxInboundConnections: 20, Meta: map[string]string{ common.SourceKey: common.SourceValue, common.DatacenterKey: "datacenter", diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml index f536c17bed..67f33517ba 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml @@ -106,6 +106,11 @@ spec: TLS SNI value to be changed to a non-connect value when federating with an external system. type: string + maxInboundConnections: + description: MaxInboundConnections is the maximum number of concurrent + inbound connections to each service instance. Defaults to 0 (using + consul's default) if not set. + type: integer meshGateway: description: MeshGateway controls the default mesh gateway configuration for this service. diff --git a/control-plane/controller/configentry_controller_test.go b/control-plane/controller/configentry_controller_test.go index 5b92feedd5..5a26d9abd6 100644 --- a/control-plane/controller/configentry_controller_test.go +++ b/control-plane/controller/configentry_controller_test.go @@ -51,7 +51,8 @@ func TestConfigEntryControllers_createsConfigEntry(t *testing.T) { Namespace: kubeNS, }, Spec: v1alpha1.ServiceDefaultsSpec{ - Protocol: "http", + Protocol: "http", + MaxInboundConnections: 100, }, }, reconciler: func(client client.Client, consulClient *capi.Client, logger logr.Logger) testReconciler { @@ -68,6 +69,7 @@ func TestConfigEntryControllers_createsConfigEntry(t *testing.T) { svcDefault, ok := consulEntry.(*capi.ServiceConfigEntry) require.True(t, ok, "cast error") require.Equal(t, "http", svcDefault.Protocol) + require.Equal(t, 100, svcDefault.MaxInboundConnections) }, }, { diff --git a/control-plane/go.mod b/control-plane/go.mod index 1848c8f435..bc8edd48ea 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -6,7 +6,7 @@ require ( github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul/api v1.14.0 + github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f github.com/hashicorp/go-hclog v0.16.1 diff --git a/control-plane/go.sum b/control-plane/go.sum index 03ca166926..8be9787ae3 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -296,8 +296,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk= -github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 h1:csNww5qBHaFqsX1eMEKVvmJ4dhqcXWj0sCkbccsSsHc= +github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= From e0ede3ea4696f7c01163bf5e99a78290f71ff38e Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Wed, 24 Aug 2022 11:20:53 -0500 Subject: [PATCH 098/235] enable nightlies for 1.11 and 1.12 and 1.13 (#1339) * enable nightlies for 1.11 and 1.12 and 1.13 --- .circleci/config.yml | 41 ++++++++++--------- acceptance/framework/config/config.go | 9 ++-- acceptance/framework/consul/helm_cluster.go | 13 +++++- acceptance/framework/flags/flags.go | 19 +++++---- .../snapshot_agent_vault_test.go | 7 ++++ 5 files changed, 56 insertions(+), 33 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 0ddc7c8302..e52b29f000 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -880,7 +880,8 @@ jobs: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.11-dev" - ENVOY_IMAGE: "envoyproxy/envoy:v1.20.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.45.0" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.47.1" + - HELM_CHART_VERSION: "0.47.1" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -902,21 +903,22 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11" -envoy-image=$ENVOY_IMAGE + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION - store_test_results: path: /tmp/test-results - store_artifacts: path: /tmp/test-results - slack/status: fail_only: true - failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.11.x nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" + failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.11 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" acceptance-kind-1-23-consul-nightly-1-12: environment: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.12-dev" - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.45.0" + - HELM_CHART_VERSION: "0.47.1" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.47.1" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -938,7 +940,7 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12" -envoy-image=$ENVOY_IMAGE + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION - store_test_results: path: /tmp/test-results - store_artifacts: @@ -952,7 +954,8 @@ jobs: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev" - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.45.0" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.47.1" + - HELM_CHART_VERSION: "0.47.1" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -974,7 +977,7 @@ jobs: - ~/.go_workspace/pkg/mod - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.13" -envoy-image=$ENVOY_IMAGE + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.13" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION - store_test_results: path: /tmp/test-results - store_artifacts: @@ -1047,15 +1050,15 @@ workflows: requires: - dev-upload-docker -# nightly-acceptance-tests-consul: -# triggers: -# - schedule: -# cron: "0 0 * * *" -# filters: -# branches: -# only: -# - main -# jobs: -# - acceptance-kind-1-23-consul-nightly-1-11 -# - acceptance-kind-1-23-consul-nightly-1-12 -# - acceptance-kind-1-23-consul-nightly-1-13 + nightly-acceptance-tests-consul: + triggers: + - schedule: + cron: "0 0 * * *" + filters: + branches: + only: + - main + jobs: + - acceptance-kind-1-23-consul-nightly-1-11 + - acceptance-kind-1-23-consul-nightly-1-12 + - acceptance-kind-1-23-consul-nightly-1-13 diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index 62fd094a33..6850839cd9 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -42,10 +42,11 @@ type TestConfig struct { DisablePeering bool - ConsulImage string - ConsulK8SImage string - ConsulVersion *version.Version - EnvoyImage string + HelmChartVersion string + ConsulImage string + ConsulK8SImage string + ConsulVersion *version.Version + EnvoyImage string NoCleanupOnFailure bool DebugDirectory string diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index 085ceda493..70e7d51502 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -86,6 +86,7 @@ func NewHelmCluster( KubectlOptions: ctx.KubectlOptions(t), Logger: logger, ExtraArgs: extraArgs, + Version: cfg.HelmChartVersion, } return &HelmCluster{ ctx: ctx, @@ -110,7 +111,11 @@ func (h *HelmCluster) Create(t *testing.T) { // Fail if there are any existing installations of the Helm chart. helpers.CheckForPriorInstallations(t, h.kubernetesClient, h.helmOptions, "consul-helm", "chart=consul-helm") - helm.Install(t, h.helmOptions, config.HelmChartPath, h.releaseName) + chartName := "hashicorp/consul" + if h.helmOptions.Version == config.HelmChartPath { + chartName = config.HelmChartPath + } + helm.Install(t, h.helmOptions, chartName, h.releaseName) k8s.WaitForAllPodsToBeReady(t, h.kubernetesClient, h.helmOptions.KubectlOptions.Namespace, fmt.Sprintf("release=%s", h.releaseName)) } @@ -271,7 +276,11 @@ func (h *HelmCluster) Upgrade(t *testing.T, helmValues map[string]string) { t.Helper() helpers.MergeMaps(h.helmOptions.SetValues, helmValues) - helm.Upgrade(t, h.helmOptions, config.HelmChartPath, h.releaseName) + chartName := "hashicorp/consul" + if h.helmOptions.Version == config.HelmChartPath { + chartName = config.HelmChartPath + } + helm.Upgrade(t, h.helmOptions, chartName, h.releaseName) k8s.WaitForAllPodsToBeReady(t, h.kubernetesClient, h.helmOptions.KubectlOptions.Namespace, fmt.Sprintf("release=%s", h.releaseName)) } diff --git a/acceptance/framework/flags/flags.go b/acceptance/framework/flags/flags.go index b275bb0904..ac11fc021d 100644 --- a/acceptance/framework/flags/flags.go +++ b/acceptance/framework/flags/flags.go @@ -29,10 +29,11 @@ type TestFlags struct { flagEnableTransparentProxy bool - flagConsulImage string - flagConsulK8sImage string - flagConsulVersion string - flagEnvoyImage string + flagHelmChartVersion string + flagConsulImage string + flagConsulK8sImage string + flagConsulVersion string + flagEnvoyImage string flagNoCleanupOnFailure bool @@ -62,6 +63,7 @@ func (t *TestFlags) init() { flag.StringVar(&t.flagConsulImage, "consul-image", "", "The Consul image to use for all tests.") flag.StringVar(&t.flagConsulK8sImage, "consul-k8s-image", "", "The consul-k8s image to use for all tests.") flag.StringVar(&t.flagConsulVersion, "consul-version", "", "The consul version used for all tests.") + flag.StringVar(&t.flagHelmChartVersion, "helm-chart-version", config.HelmChartPath, "The helm chart used for all tests.") flag.StringVar(&t.flagEnvoyImage, "envoy-image", "", "The Envoy image to use for all tests.") flag.BoolVar(&t.flagEnableMultiCluster, "enable-multi-cluster", false, @@ -146,10 +148,11 @@ func (t *TestFlags) TestConfigFromFlags() *config.TestConfig { DisablePeering: t.flagDisablePeering, - ConsulImage: t.flagConsulImage, - ConsulK8SImage: t.flagConsulK8sImage, - ConsulVersion: consulVersion, - EnvoyImage: t.flagEnvoyImage, + HelmChartVersion: t.flagHelmChartVersion, + ConsulImage: t.flagConsulImage, + ConsulK8SImage: t.flagConsulK8sImage, + ConsulVersion: consulVersion, + EnvoyImage: t.flagEnvoyImage, NoCleanupOnFailure: t.flagNoCleanupOnFailure, DebugDirectory: tempDir, diff --git a/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go b/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go index bde2d88ab0..a3ede3e984 100644 --- a/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go +++ b/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go @@ -15,6 +15,7 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/logger" "github.com/hashicorp/consul-k8s/acceptance/framework/vault" "github.com/hashicorp/go-uuid" + "github.com/hashicorp/go-version" "github.com/stretchr/testify/require" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -31,6 +32,12 @@ func TestSnapshotAgent_Vault(t *testing.T) { kubectlOptions := ctx.KubectlOptions(t) ns := kubectlOptions.Namespace + ver, err := version.NewVersion("1.12.0") + require.NoError(t, err) + if cfg.ConsulVersion != nil && cfg.ConsulVersion.LessThan(ver) { + t.Skipf("skipping this test because vault secrets backend is not supported in version %v", cfg.ConsulVersion.String()) + } + consulReleaseName := helpers.RandomName() vaultReleaseName := helpers.RandomName() From 9ac7f776dab2f813a4ab1f8ac0fee1202b718b4f Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Thu, 25 Aug 2022 12:44:39 -0400 Subject: [PATCH 099/235] Update Kubernetes versions for the nightly acceptance tests. (#1444) --- charts/consul/test/terraform/aks/main.tf | 2 +- charts/consul/test/terraform/eks/main.tf | 2 +- charts/consul/test/terraform/gke/main.tf | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/consul/test/terraform/aks/main.tf b/charts/consul/test/terraform/aks/main.tf index 57de5d2a54..784a60d9ef 100644 --- a/charts/consul/test/terraform/aks/main.tf +++ b/charts/consul/test/terraform/aks/main.tf @@ -45,7 +45,7 @@ resource "azurerm_kubernetes_cluster" "default" { location = azurerm_resource_group.default[count.index].location resource_group_name = azurerm_resource_group.default[count.index].name dns_prefix = "consul-k8s-${random_id.suffix[count.index].dec}" - kubernetes_version = "1.21.14" + kubernetes_version = "1.22.11" // We're setting the network plugin and other network properties explicitly // here even though they are the same as defaults to ensure that none of these CIDRs diff --git a/charts/consul/test/terraform/eks/main.tf b/charts/consul/test/terraform/eks/main.tf index 2a91ce528d..ad9538ac51 100644 --- a/charts/consul/test/terraform/eks/main.tf +++ b/charts/consul/test/terraform/eks/main.tf @@ -57,7 +57,7 @@ module "eks" { version = "17.20.0" cluster_name = "consul-k8s-${random_id.suffix[count.index].dec}" - cluster_version = "1.19" + cluster_version = "1.20" subnets = module.vpc[count.index].private_subnets vpc_id = module.vpc[count.index].vpc_id diff --git a/charts/consul/test/terraform/gke/main.tf b/charts/consul/test/terraform/gke/main.tf index 7f303639ad..4004b3e73d 100644 --- a/charts/consul/test/terraform/gke/main.tf +++ b/charts/consul/test/terraform/gke/main.tf @@ -10,7 +10,7 @@ resource "random_id" "suffix" { data "google_container_engine_versions" "main" { location = var.zone - version_prefix = "1.20." + version_prefix = "1.21." } resource "google_container_cluster" "cluster" { From 9688206dce5ce2c9ed36ec287d97a0bdff5ada35 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Thu, 25 Aug 2022 15:57:00 -0400 Subject: [PATCH 100/235] Remove Issue Context Bot (#1448) --- .github/workflows/issue-context-bot.yml | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 .github/workflows/issue-context-bot.yml diff --git a/.github/workflows/issue-context-bot.yml b/.github/workflows/issue-context-bot.yml deleted file mode 100644 index 51f37f7ee9..0000000000 --- a/.github/workflows/issue-context-bot.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Issue Context Bot - -on: [issues] - -jobs: - add-context: - runs-on: ubuntu-latest - steps: - - uses: wow-actions/auto-comment@v1.0.7 - with: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - issuesTransferred: | - "Hi @{{ author }}, - - It looks like your issue has been transferred to the Consul on Kubernetes repository. - If your issue is a question or bug report, there is some additional context that will - help us solve your issue. Please reply with the following information if it is not - included in your original issue: - - - the [Helm values](https://www.consul.io/docs/k8s/helm) you used to install Consul - on Kubernetes - - the version of Consul on Kubernetes used - - the version of Kubernetes you are using - - if you installed Consul on Kubernetes using Helm or the Consul-K8s CLI" From a46e208ef5202b37177d7b28a385211942699391 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 25 Aug 2022 16:54:39 -0500 Subject: [PATCH 101/235] update the helm repo prior to running helm install in acceptance tests. (#1451) * fix nightlies --- acceptance/framework/consul/helm_cluster.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/acceptance/framework/consul/helm_cluster.go b/acceptance/framework/consul/helm_cluster.go index 70e7d51502..6ae2016eaf 100644 --- a/acceptance/framework/consul/helm_cluster.go +++ b/acceptance/framework/consul/helm_cluster.go @@ -111,9 +111,16 @@ func (h *HelmCluster) Create(t *testing.T) { // Fail if there are any existing installations of the Helm chart. helpers.CheckForPriorInstallations(t, h.kubernetesClient, h.helmOptions, "consul-helm", "chart=consul-helm") - chartName := "hashicorp/consul" - if h.helmOptions.Version == config.HelmChartPath { - chartName = config.HelmChartPath + chartName := config.HelmChartPath + if h.helmOptions.Version != config.HelmChartPath { + chartName = "hashicorp/consul" + helm.AddRepo(t, h.helmOptions, "hashicorp", "https://helm.releases.hashicorp.com") + // Ignoring the error from `helm repo update` as it could fail due to stale cache or unreachable servers and we're + // asserting a chart version on Install which would fail in an obvious way should this not succeed. + _, err := helm.RunHelmCommandAndGetOutputE(t, &helm.Options{}, "repo", "update") + if err != nil { + logger.Logf(t, "Unable to update helm repository, proceeding anyway: %s.", err) + } } helm.Install(t, h.helmOptions, chartName, h.releaseName) From 04a03a567d4dd0d80ec508589cb6513ac5670cf9 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 25 Aug 2022 16:55:24 -0500 Subject: [PATCH 102/235] Lint cleanup (#1450) * Fix linting errors throughout the codebase --- acceptance/framework/config/config.go | 4 +-- acceptance/framework/config/config_test.go | 5 ++-- acceptance/framework/k8s/debug.go | 9 +++--- acceptance/framework/suite/suite.go | 4 +-- cli/cmd/proxy/read/filters.go | 28 +++++++++---------- cli/common/flag/set.go | 3 +- cli/helm/chart_test.go | 1 + .../endpoints_controller_test.go | 11 ++++---- .../connect-inject/health_checks_test.go | 11 ++++---- .../peering_acceptor_controller.go | 10 +++---- control-plane/helper/cert/source_gen_test.go | 9 +++--- control-plane/helper/test/test_util.go | 7 ++--- control-plane/subcommand/acl-init/command.go | 6 ++-- .../subcommand/acl-init/command_test.go | 23 ++++++++------- control-plane/subcommand/common/common.go | 7 ++--- .../subcommand/common/common_test.go | 11 ++++---- control-plane/subcommand/common/test_util.go | 3 +- .../connect-init/command_ent_test.go | 5 ++-- .../subcommand/connect-init/command_test.go | 13 ++++----- .../subcommand/consul-sidecar/command.go | 6 ++-- .../subcommand/consul-sidecar/command_test.go | 13 +++++---- .../subcommand/controller/command.go | 4 +-- .../create-federation-secret/command.go | 10 +++---- .../create-federation-secret/command_test.go | 25 ++++++++--------- control-plane/subcommand/flags/http.go | 4 +-- .../get-consul-client-ca/command.go | 14 +++++----- .../get-consul-client-ca/command_test.go | 17 ++++++----- .../subcommand/inject-connect/command.go | 6 ++-- .../subcommand/server-acl-init/command.go | 4 +-- .../server-acl-init/command_ent_test.go | 3 +- .../server-acl-init/command_test.go | 9 +++--- .../subcommand/service-address/command.go | 4 +-- .../service-address/command_test.go | 11 ++++---- control-plane/subcommand/tls-init/command.go | 6 ++-- .../subcommand/tls-init/command_test.go | 17 ++++++----- .../webhook-cert-manager/command.go | 3 +- .../webhook-cert-manager/command_test.go | 11 ++++---- hack/copy-crds-to-chart/main.go | 5 ++-- hack/helm-reference-gen/main.go | 7 ++--- hack/helm-reference-gen/main_test.go | 8 +++--- 40 files changed, 170 insertions(+), 187 deletions(-) diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index 6850839cd9..b457f72b5c 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -2,7 +2,7 @@ package config import ( "fmt" - "io/ioutil" + "os" "path/filepath" "strconv" "strings" @@ -109,7 +109,7 @@ func (t *TestConfig) entImage() (string, error) { } // Unmarshal values.yaml to current global.image value. - valuesContents, err := ioutil.ReadFile(filepath.Join(t.helmChartPath, "values.yaml")) + valuesContents, err := os.ReadFile(filepath.Join(t.helmChartPath, "values.yaml")) if err != nil { return "", err } diff --git a/acceptance/framework/config/config_test.go b/acceptance/framework/config/config_test.go index feb82ceb38..fb2b129678 100644 --- a/acceptance/framework/config/config_test.go +++ b/acceptance/framework/config/config_test.go @@ -2,7 +2,6 @@ package config import ( "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -151,10 +150,10 @@ func TestConfig_HelmValuesFromConfig_EntImage(t *testing.T) { valuesYAML := fmt.Sprintf(`global: image: %s `, tt.consulImage) - tmp, err := ioutil.TempDir("", "") + tmp, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(tmp) - require.NoError(t, ioutil.WriteFile(filepath.Join(tmp, "values.yaml"), []byte(valuesYAML), 0644)) + require.NoError(t, os.WriteFile(filepath.Join(tmp, "values.yaml"), []byte(valuesYAML), 0644)) cfg := TestConfig{ EnableEnterprise: true, diff --git a/acceptance/framework/k8s/debug.go b/acceptance/framework/k8s/debug.go index 8d647681f2..338c6ce995 100644 --- a/acceptance/framework/k8s/debug.go +++ b/acceptance/framework/k8s/debug.go @@ -3,7 +3,6 @@ package k8s import ( "context" "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -46,7 +45,7 @@ func WritePodsDebugInfoIfFailed(t *testing.T, kubectlOptions *k8s.KubectlOptions // Write logs or err to file name .log logFilename := filepath.Join(testDebugDirectory, fmt.Sprintf("%s.log", pod.Name)) - require.NoError(t, ioutil.WriteFile(logFilename, []byte(logs), 0600)) + require.NoError(t, os.WriteFile(logFilename, []byte(logs), 0600)) // Describe pod and write it to a file. writeResourceInfoToFile(t, pod.Name, "pod", testDebugDirectory, kubectlOptions) @@ -71,8 +70,8 @@ func WritePodsDebugInfoIfFailed(t *testing.T, kubectlOptions *k8s.KubectlOptions // Write config/clusters or err to file name -envoy-[configdump/clusters].json configDumpFilename := filepath.Join(testDebugDirectory, fmt.Sprintf("%s-envoy-configdump.json", mpod.Name)) clustersFilename := filepath.Join(testDebugDirectory, fmt.Sprintf("%s-envoy-clusters.json", mpod.Name)) - require.NoError(t, ioutil.WriteFile(configDumpFilename, []byte(configDump), 0600)) - require.NoError(t, ioutil.WriteFile(clustersFilename, []byte(clusters), 0600)) + require.NoError(t, os.WriteFile(configDumpFilename, []byte(configDump), 0600)) + require.NoError(t, os.WriteFile(clustersFilename, []byte(clusters), 0600)) } @@ -146,5 +145,5 @@ func writeResourceInfoToFile(t *testing.T, resourceName, resourceType, testDebug desc = fmt.Sprintf("Error describing %s/%s: %s: %s", resourceType, resourceType, err, desc) } descFilename := filepath.Join(testDebugDirectory, fmt.Sprintf("%s-%s.txt", resourceName, resourceType)) - require.NoError(t, ioutil.WriteFile(descFilename, []byte(desc), 0600)) + require.NoError(t, os.WriteFile(descFilename, []byte(desc), 0600)) } diff --git a/acceptance/framework/suite/suite.go b/acceptance/framework/suite/suite.go index 365737f66f..67dff4f587 100644 --- a/acceptance/framework/suite/suite.go +++ b/acceptance/framework/suite/suite.go @@ -3,7 +3,7 @@ package suite import ( "flag" "fmt" - "io/ioutil" + "os" "testing" "github.com/hashicorp/consul-k8s/acceptance/framework/config" @@ -49,7 +49,7 @@ func (s *suite) Run() int { // Create test debug directory if it doesn't exist if s.cfg.DebugDirectory == "" { var err error - s.cfg.DebugDirectory, err = ioutil.TempDir("", "consul-test") + s.cfg.DebugDirectory, err = os.MkdirTemp("", "consul-test") if err != nil { fmt.Printf("Failed to create debug directory: %s\n", err) return 1 diff --git a/cli/cmd/proxy/read/filters.go b/cli/cmd/proxy/read/filters.go index c9d2d8f796..dc65172f32 100644 --- a/cli/cmd/proxy/read/filters.go +++ b/cli/cmd/proxy/read/filters.go @@ -8,12 +8,12 @@ import ( // FilterClusters takes a slice of clusters along with parameters for filtering // those clusters. // -// - `fqdn` filters clusters to only those with fully qualified domain names -// which contain the given value. -// - `address` filters clusters to only those with endpoint addresses which -// contain the given value. -// - `port` filters clusters to only those with endpoint addresses with ports -// that match the given value. If -1 is passed, no filtering will occur. +// - `fqdn` filters clusters to only those with fully qualified domain names +// which contain the given value. +// - `address` filters clusters to only those with endpoint addresses which +// contain the given value. +// - `port` filters clusters to only those with endpoint addresses with ports +// that match the given value. If -1 is passed, no filtering will occur. // // The filters are applied in combination such that a cluster must adhere to // all of the filtering values which are passed in. @@ -51,10 +51,10 @@ func FilterClusters(clusters []Cluster, fqdn, address string, port int) []Cluste // FilterEndpoints takes a slice of endpoints along with parameters for filtering // those endpoints: // -// - `address` filters endpoints to only those with an address which contains -// the given value. -// - `port` filters endpoints to only those with an address which has a port -// that matches the given value. If -1 is passed, no filtering will occur. +// - `address` filters endpoints to only those with an address which contains +// the given value. +// - `port` filters endpoints to only those with an address which has a port +// that matches the given value. If -1 is passed, no filtering will occur. // // The filters are applied in combination such that an endpoint must adhere to // all of the filtering values which are passed in. @@ -78,10 +78,10 @@ func FilterEndpoints(endpoints []Endpoint, address string, port int) []Endpoint // FilterListeners takes a slice of listeners along with parameters for filtering // those endpoints: // -// - `address` filters listeners to only those with an address which contains -// the given value. -// - `port` filters listeners to only those with an address which has a port -// that matches the given value. If -1 is passed, no filtering will occur. +// - `address` filters listeners to only those with an address which contains +// the given value. +// - `port` filters listeners to only those with an address which has a port +// that matches the given value. If -1 is passed, no filtering will occur. // // The filters are applied in combination such that an listener must adhere to // all of the filtering values which are passed in. diff --git a/cli/common/flag/set.go b/cli/common/flag/set.go index 94c8e184c2..6e5e615555 100644 --- a/cli/common/flag/set.go +++ b/cli/common/flag/set.go @@ -5,7 +5,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "strings" "github.com/posener/complete" @@ -34,7 +33,7 @@ func NewSets() *Sets { // Errors and usage are expected to be controlled externally by // checking on the result of Parse. unionSet.Usage = func() {} - unionSet.SetOutput(ioutil.Discard) + unionSet.SetOutput(io.Discard) return &Sets{ unionSet: unionSet, diff --git a/cli/helm/chart_test.go b/cli/helm/chart_test.go index 71fa6355be..9ed48d50a5 100644 --- a/cli/helm/chart_test.go +++ b/cli/helm/chart_test.go @@ -8,6 +8,7 @@ import ( ) // Embed a test chart to test against. +// //go:embed test_fixtures/consul/* test_fixtures/consul/templates/_helpers.tpl var testChartFiles embed.FS diff --git a/control-plane/connect-inject/endpoints_controller_test.go b/control-plane/connect-inject/endpoints_controller_test.go index 741c7571ee..19cda9a206 100644 --- a/control-plane/connect-inject/endpoints_controller_test.go +++ b/control-plane/connect-inject/endpoints_controller_test.go @@ -1830,13 +1830,14 @@ func TestReconcileCreateEndpoint(t *testing.T) { // Tests updating an Endpoints object. // - Tests updates via the register codepath: -// - When an address in an Endpoint is updated, that the corresponding service instance in Consul is updated. -// - When an address is added to an Endpoint, an additional service instance in Consul is registered. -// - When an address in an Endpoint is updated - via health check change - the corresponding service instance is updated. +// - When an address in an Endpoint is updated, that the corresponding service instance in Consul is updated. +// - When an address is added to an Endpoint, an additional service instance in Consul is registered. +// - When an address in an Endpoint is updated - via health check change - the corresponding service instance is updated. // - Tests updates via the deregister codepath: -// - When an address is removed from an Endpoint, the corresponding service instance in Consul is deregistered. -// - When an address is removed from an Endpoint *and there are no addresses left in the Endpoint*, the +// - When an address is removed from an Endpoint, the corresponding service instance in Consul is deregistered. +// - When an address is removed from an Endpoint *and there are no addresses left in the Endpoint*, the // corresponding service instance in Consul is deregistered. +// // For the register and deregister codepath, this also tests that they work when the Consul service name is different // from the K8s service name. // This test covers EndpointsController.deregisterServiceOnAllAgents when services should be selectively deregistered diff --git a/control-plane/connect-inject/health_checks_test.go b/control-plane/connect-inject/health_checks_test.go index 0bf5cb7d29..8816e6e5bb 100644 --- a/control-plane/connect-inject/health_checks_test.go +++ b/control-plane/connect-inject/health_checks_test.go @@ -1,10 +1,11 @@ package connectinject import ( - "github.com/stretchr/testify/require" - "io/ioutil" + "os" "path/filepath" "testing" + + "github.com/stretchr/testify/require" ) func TestReady(t *testing.T) { @@ -26,14 +27,14 @@ func TestReady(t *testing.T) { for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(t, err) if tt.certFileContents != nil { - err := ioutil.WriteFile(filepath.Join(tmpDir, "tls.crt"), []byte(*tt.certFileContents), 0666) + err := os.WriteFile(filepath.Join(tmpDir, "tls.crt"), []byte(*tt.certFileContents), 0666) require.NoError(t, err) } if tt.keyFileContents != nil { - err := ioutil.WriteFile(filepath.Join(tmpDir, "tls.key"), []byte(*tt.keyFileContents), 0666) + err := os.WriteFile(filepath.Join(tmpDir, "tls.key"), []byte(*tt.keyFileContents), 0666) require.NoError(t, err) } rc := ReadinessCheck{tmpDir} diff --git a/control-plane/connect-inject/peering_acceptor_controller.go b/control-plane/connect-inject/peering_acceptor_controller.go index c124c08b55..1125c96b51 100644 --- a/control-plane/connect-inject/peering_acceptor_controller.go +++ b/control-plane/connect-inject/peering_acceptor_controller.go @@ -56,11 +56,11 @@ const ( // move the current state of the cluster closer to the desired state. // PeeringAcceptor resources determine whether to generate a new peering token in Consul and store it in the backend // specified in the spec. -// - If the resource doesn't exist, the peering should be deleted in Consul. -// - If the resource exists, and a peering doesn't exist in Consul, it should be created. -// - If the resource exists, and a peering does exist in Consul, it should be reconciled. -// - If the status of the resource does not match the current state of the specified secret, generate a new token -// and store it according to the spec. +// - If the resource doesn't exist, the peering should be deleted in Consul. +// - If the resource exists, and a peering doesn't exist in Consul, it should be created. +// - If the resource exists, and a peering does exist in Consul, it should be reconciled. +// - If the status of the resource does not match the current state of the specified secret, generate a new token +// and store it according to the spec. // // NOTE: It is possible that Reconcile is called multiple times concurrently because we're watching // two different resource kinds. As a result, we need to make sure that the code in this method diff --git a/control-plane/helper/cert/source_gen_test.go b/control-plane/helper/cert/source_gen_test.go index 8926e89174..b68ffc7e13 100644 --- a/control-plane/helper/cert/source_gen_test.go +++ b/control-plane/helper/cert/source_gen_test.go @@ -2,7 +2,6 @@ package cert import ( "context" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -78,15 +77,15 @@ func testGenSource() *GenSource { func testBundleDir(t *testing.T, bundle *Bundle, dir string) string { if dir == "" { // Create a temporary directory for storing the certs - td, err := ioutil.TempDir("", "consul") + td, err := os.MkdirTemp("", "consul") require.NoError(t, err) dir = td } // Write the cert - require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "ca.pem"), bundle.CACert, 0644)) - require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "leaf.pem"), bundle.Cert, 0644)) - require.NoError(t, ioutil.WriteFile(filepath.Join(dir, "leaf.key.pem"), bundle.Key, 0644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "ca.pem"), bundle.CACert, 0644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "leaf.pem"), bundle.Cert, 0644)) + require.NoError(t, os.WriteFile(filepath.Join(dir, "leaf.key.pem"), bundle.Key, 0644)) return dir } diff --git a/control-plane/helper/test/test_util.go b/control-plane/helper/test/test_util.go index 142aa535c5..08b28b00fd 100644 --- a/control-plane/helper/test/test_util.go +++ b/control-plane/helper/test/test_util.go @@ -2,7 +2,6 @@ package test import ( "fmt" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -26,13 +25,13 @@ const ( func GenerateServerCerts(t *testing.T) (string, string, string) { require := require.New(t) - caFile, err := ioutil.TempFile("", "ca") + caFile, err := os.CreateTemp("", "ca") require.NoError(err) - certFile, err := ioutil.TempFile("", "cert") + certFile, err := os.CreateTemp("", "cert") require.NoError(err) - certKeyFile, err := ioutil.TempFile("", "key") + certKeyFile, err := os.CreateTemp("", "key") require.NoError(err) // Generate CA diff --git a/control-plane/subcommand/acl-init/command.go b/control-plane/subcommand/acl-init/command.go index 865d96b261..f045dda076 100644 --- a/control-plane/subcommand/acl-init/command.go +++ b/control-plane/subcommand/acl-init/command.go @@ -6,7 +6,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "path/filepath" "strings" "sync" @@ -237,7 +237,7 @@ func (c *Command) Run(args []string) int { // Write the data out as a file. // Must be 0644 because this is written by the consul-k8s user but needs // to be readable by the consul user. - err = ioutil.WriteFile(filepath.Join(c.flagACLDir, "acl-config.json"), buf.Bytes(), 0644) + err = os.WriteFile(filepath.Join(c.flagACLDir, "acl-config.json"), buf.Bytes(), 0644) if err != nil { c.logger.Error("Error writing config file", "error", err) return 1 @@ -247,7 +247,7 @@ func (c *Command) Run(args []string) int { if c.flagTokenSinkFile != "" { // Must be 0600 in case this command is re-run. In that case we need // to have permissions to overwrite our file. - err := ioutil.WriteFile(c.flagTokenSinkFile, []byte(secret), 0600) + err := os.WriteFile(c.flagTokenSinkFile, []byte(secret), 0600) if err != nil { c.logger.Error("Error writing token to file", "file", c.flagTokenSinkFile, "error", err) return 1 diff --git a/control-plane/subcommand/acl-init/command_test.go b/control-plane/subcommand/acl-init/command_test.go index a1d0043a3a..f069b5ec98 100644 --- a/control-plane/subcommand/acl-init/command_test.go +++ b/control-plane/subcommand/acl-init/command_test.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -54,7 +53,7 @@ func TestRun_FlagValidation(t *testing.T) { func TestRun_TokenSinkFile(t *testing.T) { t.Parallel() require := require.New(t) - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(err) defer os.RemoveAll(tmpDir) @@ -90,7 +89,7 @@ func TestRun_TokenSinkFile(t *testing.T) { "-consul-api-timeout", "5s", }) require.Equal(0, code, ui.ErrorWriter.String()) - bytes, err := ioutil.ReadFile(sinkFile) + bytes, err := os.ReadFile(sinkFile) require.NoError(err) require.Equal(token, string(bytes), "exp: %s, got: %s", token, string(bytes)) } @@ -140,7 +139,7 @@ func TestRun_TokenSinkFileErr(t *testing.T) { func TestRun_TokenSinkFileTwice(t *testing.T) { t.Parallel() require := require.New(t) - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(err) defer os.RemoveAll(tmpDir) @@ -180,7 +179,7 @@ func TestRun_TokenSinkFileTwice(t *testing.T) { }) require.Equal(0, code, ui.ErrorWriter.String()) - bytes, err := ioutil.ReadFile(sinkFile) + bytes, err := os.ReadFile(sinkFile) require.NoError(err) require.Equal(token, string(bytes), "exp: %s, got: %s", token, string(bytes)) } @@ -233,7 +232,7 @@ func TestRun_PerformsConsulLogin(t *testing.T) { }) require.Equal(t, 0, code, ui.ErrorWriter.String()) // Validate the Token got written. - tokenBytes, err := ioutil.ReadFile(tokenFile) + tokenBytes, err := os.ReadFile(tokenFile) require.NoError(t, err) require.Equal(t, 36, len(tokenBytes)) // Validate the Token and its Description. @@ -248,7 +247,7 @@ func TestRun_PerformsConsulLogin(t *testing.T) { func TestRun_WithAclAuthMethodDefined_WritesConfigJson_WithTokenMatchingSinkFile(t *testing.T) { tokenFile := common.WriteTempFile(t, "") bearerFile := common.WriteTempFile(t, test.ServiceAccountJWTToken) - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(t, err) t.Cleanup(func() { os.Remove(tokenFile) @@ -298,10 +297,10 @@ func TestRun_WithAclAuthMethodDefined_WritesConfigJson_WithTokenMatchingSinkFile }) require.Equal(t, 0, code, ui.ErrorWriter.String()) // Validate the ACL Config file got written. - aclConfigBytes, err := ioutil.ReadFile(fmt.Sprintf("%s/acl-config.json", tmpDir)) + aclConfigBytes, err := os.ReadFile(fmt.Sprintf("%s/acl-config.json", tmpDir)) require.NoError(t, err) // Validate the Token Sink File got written. - sinkFileToken, err := ioutil.ReadFile(tokenFile) + sinkFileToken, err := os.ReadFile(tokenFile) require.NoError(t, err) // Validate the Token Sink File Matches the ACL Cconfig Token by injecting // the token secret into the template used by the ACL config file. @@ -320,7 +319,7 @@ func TestRun_WithAclAuthMethodDefined_WritesConfigJson_WithTokenMatchingSinkFile func TestRun_WithoutAclAuthMethodDefined_WritesConfigJsonWithTokenMatchingSinkFile(t *testing.T) { t.Parallel() require := require.New(t) - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(err) t.Cleanup(func() { @@ -361,11 +360,11 @@ func TestRun_WithoutAclAuthMethodDefined_WritesConfigJsonWithTokenMatchingSinkFi "-consul-api-timeout", "5s", }) // Validate the ACL Config file got written. - aclConfigBytes, err := ioutil.ReadFile(fmt.Sprintf("%s/acl-config.json", tmpDir)) + aclConfigBytes, err := os.ReadFile(fmt.Sprintf("%s/acl-config.json", tmpDir)) require.NoError(err) // Validate the Token Sink File got written. require.Equal(0, code, ui.ErrorWriter.String()) - sinkFileToken, err := ioutil.ReadFile(sinkFile) + sinkFileToken, err := os.ReadFile(sinkFile) require.NoError(err) // Validate the Token Sink File Matches the ACL Cconfig Token by injecting // the token secret into the template used by the ACL config file. diff --git a/control-plane/subcommand/common/common.go b/control-plane/subcommand/common/common.go index a5da023fc3..5b8479c9ab 100644 --- a/control-plane/subcommand/common/common.go +++ b/control-plane/subcommand/common/common.go @@ -3,7 +3,6 @@ package common import ( "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -108,7 +107,7 @@ type LoginParams struct { // The logic of this is taken from the `consul login` command. func ConsulLogin(client *api.Client, params LoginParams, log hclog.Logger) (string, error) { // Read the bearerTokenFile. - data, err := ioutil.ReadFile(params.BearerTokenFile) + data, err := os.ReadFile(params.BearerTokenFile) if err != nil { return "", fmt.Errorf("unable to read bearer token file: %v, err: %v", params.BearerTokenFile, err) } @@ -198,7 +197,7 @@ func ConsulLogin(client *api.Client, params LoginParams, log hclog.Logger) (stri return token.SecretID, nil } -// WriteFileWithPerms will write payload as the contents of the outputFile and set permissions after writing the contents. This function is necessary since using ioutil.WriteFile() alone will create the new file with the requested permissions prior to actually writing the file, so you can't set read-only permissions. +// WriteFileWithPerms will write payload as the contents of the outputFile and set permissions after writing the contents. This function is necessary since using os.WriteFile() alone will create the new file with the requested permissions prior to actually writing the file, so you can't set read-only permissions. func WriteFileWithPerms(outputFile, payload string, mode os.FileMode) error { // os.WriteFile truncates existing files and overwrites them, but only if they are writable. // If the file exists it will already likely be read-only. Remove it first. @@ -207,7 +206,7 @@ func WriteFileWithPerms(outputFile, payload string, mode os.FileMode) error { return fmt.Errorf("unable to delete existing file: %s", err) } } - if err := ioutil.WriteFile(outputFile, []byte(payload), os.ModePerm); err != nil { + if err := os.WriteFile(outputFile, []byte(payload), os.ModePerm); err != nil { return fmt.Errorf("unable to write file: %s", err) } return os.Chmod(outputFile, mode) diff --git a/control-plane/subcommand/common/common_test.go b/control-plane/subcommand/common/common_test.go index a58fbfe441..9bab362560 100644 --- a/control-plane/subcommand/common/common_test.go +++ b/control-plane/subcommand/common/common_test.go @@ -2,7 +2,6 @@ package common import ( "fmt" - "io/ioutil" "math/rand" "net/http" "net/http/httptest" @@ -71,7 +70,7 @@ func TestConsulLogin(t *testing.T) { _, err = ConsulLogin(client, params, log) require.NoError(t, err) // Validate that the token file was written to disk. - data, err := ioutil.ReadFile(tokenFile) + data, err := os.ReadFile(tokenFile) require.NoError(t, err) require.Equal(t, string(data), "b78d37c7-0ca7-5f4d-99ee-6d9975ce4586") } @@ -119,7 +118,7 @@ func TestConsulLogin_Retries(t *testing.T) { require.NoError(t, err) require.Equal(t, 2, numLoginCalls) // Validate that the token file was written to disk. - data, err := ioutil.ReadFile(tokenFile) + data, err := os.ReadFile(tokenFile) require.NoError(t, err) require.Equal(t, string(data), "b78d37c7-0ca7-5f4d-99ee-6d9975ce4586") } @@ -221,7 +220,7 @@ func TestWriteFileWithPerms_OutputFileExists(t *testing.T) { t.Parallel() rand.Seed(time.Now().UnixNano()) randFileName := fmt.Sprintf("/tmp/%d", rand.Int()) - err := ioutil.WriteFile(randFileName, []byte("foo"), os.FileMode(0444)) + err := os.WriteFile(randFileName, []byte("foo"), os.FileMode(0444)) require.NoError(t, err) t.Cleanup(func() { os.Remove(randFileName) @@ -229,7 +228,7 @@ func TestWriteFileWithPerms_OutputFileExists(t *testing.T) { payload := "abcd" err = WriteFileWithPerms(randFileName, payload, os.FileMode(0444)) require.NoError(t, err) - data, err := ioutil.ReadFile(randFileName) + data, err := os.ReadFile(randFileName) require.NoError(t, err) require.Equal(t, payload, string(data)) } @@ -252,7 +251,7 @@ func TestWriteFileWithPerms(t *testing.T) { require.Equal(t, file.Mode(), mode) require.Equal(t, file.Size(), int64(len(payload))) // Validate the data was written correctly. - data, err := ioutil.ReadFile(randFileName) + data, err := os.ReadFile(randFileName) require.NoError(t, err) require.Equal(t, payload, string(data)) } diff --git a/control-plane/subcommand/common/test_util.go b/control-plane/subcommand/common/test_util.go index cf53239841..ff73e62ae3 100644 --- a/control-plane/subcommand/common/test_util.go +++ b/control-plane/subcommand/common/test_util.go @@ -1,7 +1,6 @@ package common import ( - "io/ioutil" "os" "testing" @@ -12,7 +11,7 @@ import ( // name. It will remove the file once the test completes. func WriteTempFile(t *testing.T, contents string) string { t.Helper() - file, err := ioutil.TempFile("", "testName") + file, err := os.CreateTemp("", "testName") require.NoError(t, err) _, err = file.WriteString(contents) require.NoError(t, err) diff --git a/control-plane/subcommand/connect-init/command_ent_test.go b/control-plane/subcommand/connect-init/command_ent_test.go index 5ed43e0353..4e23fb2244 100644 --- a/control-plane/subcommand/connect-init/command_ent_test.go +++ b/control-plane/subcommand/connect-init/command_ent_test.go @@ -4,7 +4,6 @@ package connectinit import ( "fmt" - "io/ioutil" "math/rand" "os" "testing" @@ -211,7 +210,7 @@ func TestRun_ServicePollingWithACLsAndTLSWithNamespaces(t *testing.T) { if c.acls { // Validate the ACL token was written. - tokenData, err := ioutil.ReadFile(tokenFile) + tokenData, err := os.ReadFile(tokenFile) require.NoError(t, err) require.NotEmpty(t, tokenData) @@ -224,7 +223,7 @@ func TestRun_ServicePollingWithACLsAndTLSWithNamespaces(t *testing.T) { } // Validate contents of proxyFile. - data, err := ioutil.ReadFile(proxyFile) + data, err := os.ReadFile(proxyFile) require.NoError(t, err) require.Contains(t, string(data), "counting-counting-sidecar-proxy") }) diff --git a/control-plane/subcommand/connect-init/command_test.go b/control-plane/subcommand/connect-init/command_test.go index 515b8798eb..58514d98d9 100644 --- a/control-plane/subcommand/connect-init/command_test.go +++ b/control-plane/subcommand/connect-init/command_test.go @@ -2,7 +2,6 @@ package connectinit import ( "fmt" - "io/ioutil" "math/rand" "net/http" "net/http/httptest" @@ -218,7 +217,7 @@ func TestRun_ServicePollingWithACLsAndTLS(t *testing.T) { require.Equal(t, 0, code, ui.ErrorWriter.String()) // Validate the ACL token was written. - tokenData, err := ioutil.ReadFile(tokenFile) + tokenData, err := os.ReadFile(tokenFile) require.NoError(t, err) require.NotEmpty(t, tokenData) @@ -230,7 +229,7 @@ func TestRun_ServicePollingWithACLsAndTLS(t *testing.T) { require.Equal(t, "token created via login: {\"pod\":\"default-ns/counting-pod\"}", token.Description) // Validate contents of proxyFile. - data, err := ioutil.ReadFile(proxyFile) + data, err := os.ReadFile(proxyFile) require.NoError(t, err) if tt.multiport { require.Contains(t, string(data), "counting-admin-sidecar-proxy-id") @@ -340,7 +339,7 @@ func TestRun_ServicePollingOnly(t *testing.T) { require.Equal(t, 0, code, ui.ErrorWriter.String()) // Validate contents of proxyFile. - data, err := ioutil.ReadFile(proxyFile) + data, err := os.ReadFile(proxyFile) require.NoError(t, err) if tt.multiport { require.Contains(t, string(data), "counting-admin-sidecar-proxy-id") @@ -576,7 +575,7 @@ func TestRun_RetryServicePolling(t *testing.T) { require.Equal(t, 0, code) // Validate contents of proxyFile. - data, err := ioutil.ReadFile(proxyFile) + data, err := os.ReadFile(proxyFile) require.NoError(t, err) require.Contains(t, string(data), "counting-counting-sidecar-proxy") } @@ -766,11 +765,11 @@ func TestRun_LoginWithRetries(t *testing.T) { // Cmd will return 1 after numACLLoginRetries, so bound LoginAttemptsCount if we exceeded it. require.Equal(t, c.LoginAttemptsCount, counter) // Validate that the token was written to disk if we succeeded. - tokenData, err := ioutil.ReadFile(tokenFile) + tokenData, err := os.ReadFile(tokenFile) require.NoError(t, err) require.Equal(t, "b78d37c7-0ca7-5f4d-99ee-6d9975ce4586", string(tokenData)) // Validate contents of proxyFile. - proxydata, err := ioutil.ReadFile(proxyFile) + proxydata, err := os.ReadFile(proxyFile) require.NoError(t, err) require.Equal(t, "counting-counting-sidecar-proxy", string(proxydata)) }) diff --git a/control-plane/subcommand/consul-sidecar/command.go b/control-plane/subcommand/consul-sidecar/command.go index 61bfa1a5c7..6ea77f635c 100644 --- a/control-plane/subcommand/consul-sidecar/command.go +++ b/control-plane/subcommand/consul-sidecar/command.go @@ -5,7 +5,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "io" "net/http" "os" "os/exec" @@ -285,7 +285,7 @@ func (c *Command) mergedMetricsHandler(rw http.ResponseWriter, _ *http.Request) c.logger.Error(fmt.Sprintf("Error closing envoy metrics body: %s", err.Error())) } }() - envoyMetricsBody, err := ioutil.ReadAll(envoyMetrics.Body) + envoyMetricsBody, err := io.ReadAll(envoyMetrics.Body) if err != nil { c.logger.Error("Could not read Envoy proxy metrics", "err", err) http.Error(rw, fmt.Sprintf("Could not read Envoy proxy metrics: %s", err), http.StatusInternalServerError) @@ -316,7 +316,7 @@ func (c *Command) mergedMetricsHandler(rw http.ResponseWriter, _ *http.Request) c.logger.Error(fmt.Sprintf("Error closing service metrics body: %s", err.Error())) } }() - serviceMetricsBody, err := ioutil.ReadAll(serviceMetrics.Body) + serviceMetricsBody, err := io.ReadAll(serviceMetrics.Body) if err != nil { c.logger.Error("Could not read service metrics", "err", err) writeResponse(rw, serviceMetricSuccess(false), "service metrics success", c.logger) diff --git a/control-plane/subcommand/consul-sidecar/command_test.go b/control-plane/subcommand/consul-sidecar/command_test.go index 4c66abab92..cd2d024ec5 100644 --- a/control-plane/subcommand/consul-sidecar/command_test.go +++ b/control-plane/subcommand/consul-sidecar/command_test.go @@ -3,7 +3,8 @@ package consulsidecar import ( "bytes" "fmt" - "io/ioutil" + "io" + "net" "net/http" "os" @@ -224,7 +225,7 @@ type mockEnvoyMetricsGetter struct { func (em *mockEnvoyMetricsGetter) Get(_ string) (resp *http.Response, err error) { response := &http.Response{} response.StatusCode = em.respStatusCode - response.Body = ioutil.NopCloser(bytes.NewReader([]byte("envoy metrics\n"))) + response.Body = io.NopCloser(bytes.NewReader([]byte("envoy metrics\n"))) return response, nil } @@ -242,7 +243,7 @@ func (sm *mockServiceMetricsGetter) Get(url string) (resp *http.Response, err er sm.reqURL = url response := &http.Response{} - response.Body = ioutil.NopCloser(bytes.NewReader([]byte("service metrics\n"))) + response.Body = io.NopCloser(bytes.NewReader([]byte("service metrics\n"))) response.StatusCode = sm.respStatusCode return response, nil @@ -329,7 +330,7 @@ func TestMergedMetricsServer(t *testing.T) { retry.Run(t, func(r *retry.R) { resp, err := http.Get(fmt.Sprintf("http://127.0.0.1:%d/stats/prometheus", randomPorts[0])) require.NoError(r, err) - bytes, err := ioutil.ReadAll(resp.Body) + bytes, err := io.ReadAll(resp.Body) require.NoError(r, err) require.Equal(r, c.expectedOutput, string(bytes)) // Verify the correct service metrics url was used. The service @@ -613,11 +614,11 @@ func stopCommand(t *testing.T, cmd *Command, exitChan chan int) { // createServicesTmpFile creates a temp directory // and writes servicesRegistration as an HCL file there. func createServicesTmpFile(t *testing.T, serviceHCL string) (string, string) { - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(t, err) configFile := filepath.Join(tmpDir, "svc.hcl") - err = ioutil.WriteFile(configFile, []byte(serviceHCL), 0600) + err = os.WriteFile(configFile, []byte(serviceHCL), 0600) require.NoError(t, err) return tmpDir, configFile diff --git a/control-plane/subcommand/controller/command.go b/control-plane/subcommand/controller/command.go index f5815b0dfa..083eb72711 100644 --- a/control-plane/subcommand/controller/command.go +++ b/control-plane/subcommand/controller/command.go @@ -5,7 +5,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "sync" "github.com/hashicorp/consul-k8s/control-plane/api/common" @@ -365,7 +365,7 @@ func (c *Command) updateWebhookCABundle() error { webhookConfigName := fmt.Sprintf("%s-controller", c.flagResourcePrefix) caPath := fmt.Sprintf("%s/%s", c.flagWebhookTLSCertDir, WebhookCAFilename) - caCert, err := ioutil.ReadFile(caPath) + caCert, err := os.ReadFile(caPath) if err != nil { return err } diff --git a/control-plane/subcommand/create-federation-secret/command.go b/control-plane/subcommand/create-federation-secret/command.go index 1cd1107108..3a96e18134 100644 --- a/control-plane/subcommand/create-federation-secret/command.go +++ b/control-plane/subcommand/create-federation-secret/command.go @@ -6,7 +6,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "strings" "sync" "time" @@ -137,7 +137,7 @@ func (c *Command) Run(args []string) int { // Add gossip encryption key if it exists. if c.flagGossipKeyFile != "" { logger.Info("Retrieving gossip encryption key data") - gossipKey, err := ioutil.ReadFile(c.flagGossipKeyFile) + gossipKey, err := os.ReadFile(c.flagGossipKeyFile) if err != nil { c.UI.Error(fmt.Sprintf("Error reading gossip encryption key file: %s", err)) return 1 @@ -152,7 +152,7 @@ func (c *Command) Run(args []string) int { // Add server CA cert. logger.Info("Retrieving server CA cert data") - caCert, err := ioutil.ReadFile(c.flagServerCACertFile) + caCert, err := os.ReadFile(c.flagServerCACertFile) if err != nil { c.UI.Error(fmt.Sprintf("Error reading server CA cert file: %s", err)) return 1 @@ -162,7 +162,7 @@ func (c *Command) Run(args []string) int { // Add server CA key. logger.Info("Retrieving server CA key data") - caKey, err := ioutil.ReadFile(c.flagServerCAKeyFile) + caKey, err := os.ReadFile(c.flagServerCAKeyFile) if err != nil { c.UI.Error(fmt.Sprintf("Error reading server CA key file: %s", err)) return 1 @@ -432,7 +432,7 @@ func (c *Command) validateCAFileFlag() error { if cfg.TLSConfig.CAFile == "" { return errors.New("-ca-file or CONSUL_CACERT must be set") } - _, err := ioutil.ReadFile(cfg.TLSConfig.CAFile) + _, err := os.ReadFile(cfg.TLSConfig.CAFile) if err != nil { return fmt.Errorf("error reading CA file: %s", err) } diff --git a/control-plane/subcommand/create-federation-secret/command_test.go b/control-plane/subcommand/create-federation-secret/command_test.go index 0fe867c869..dca207d8f1 100644 --- a/control-plane/subcommand/create-federation-secret/command_test.go +++ b/control-plane/subcommand/create-federation-secret/command_test.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "os" "strconv" "strings" @@ -27,7 +26,7 @@ import ( func TestRun_FlagValidation(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -100,7 +99,7 @@ func TestRun_FlagValidation(t *testing.T) { func TestRun_CAFileMissing(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -123,7 +122,7 @@ func TestRun_CAFileMissing(t *testing.T) { func TestRun_ServerCACertFileMissing(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -146,7 +145,7 @@ func TestRun_ServerCACertFileMissing(t *testing.T) { func TestRun_ServerCAKeyFileMissing(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -169,7 +168,7 @@ func TestRun_ServerCAKeyFileMissing(t *testing.T) { func TestRun_GossipEncryptionKeyFileMissing(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -193,7 +192,7 @@ func TestRun_GossipEncryptionKeyFileMissing(t *testing.T) { func TestRun_GossipEncryptionKeyFileEmpty(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -219,7 +218,7 @@ func TestRun_GossipEncryptionKeyFileEmpty(t *testing.T) { // token key, we return error. func TestRun_ReplicationTokenMissingExpectedKey(t *testing.T) { t.Parallel() - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(f.Name()) @@ -425,9 +424,9 @@ func TestRun_ACLs_K8SNamespaces_ResourcePrefixes(tt *testing.T) { gossipEncryptionKey := "oGaLv60gQ0E+Uvn+Lokz9APjbu5fJaYx7kglOmg4jZc=" var gossipKeyFile string if c.gossipKey { - f, err := ioutil.TempFile("", "") + f, err := os.CreateTemp("", "") require.NoError(t, err) - err = ioutil.WriteFile(f.Name(), []byte(gossipEncryptionKey), 0644) + err = os.WriteFile(f.Name(), []byte(gossipEncryptionKey), 0644) require.NoError(t, err) gossipKeyFile = f.Name() } @@ -463,13 +462,13 @@ func TestRun_ACLs_K8SNamespaces_ResourcePrefixes(tt *testing.T) { // CA Cert require.Contains(t, secret.Data, "caCert") - caFileBytes, err := ioutil.ReadFile(caFile) + caFileBytes, err := os.ReadFile(caFile) require.NoError(t, err) require.Equal(t, string(caFileBytes), string(secret.Data["caCert"])) // CA Key require.Contains(t, secret.Data, "caKey") - keyFileBytes, err := ioutil.ReadFile(keyFile) + keyFileBytes, err := os.ReadFile(keyFile) require.NoError(t, err) require.Equal(t, string(keyFileBytes), string(secret.Data["caKey"])) @@ -1119,7 +1118,7 @@ func TestRun_Autoencrypt(t *testing.T) { require.NoError(t, err) require.Contains(t, secret.Data, "caCert") - keyFileBytes, err := ioutil.ReadFile(keyFile) + keyFileBytes, err := os.ReadFile(keyFile) require.NoError(t, err) require.Equal(t, string(keyFileBytes), string(secret.Data["caCert"])) } diff --git a/control-plane/subcommand/flags/http.go b/control-plane/subcommand/flags/http.go index db06345cd5..c9232b26e2 100644 --- a/control-plane/subcommand/flags/http.go +++ b/control-plane/subcommand/flags/http.go @@ -2,7 +2,7 @@ package flags import ( "flag" - "io/ioutil" + "os" "strings" "time" @@ -96,7 +96,7 @@ func (f *HTTPFlags) ReadTokenFile() (string, error) { return "", nil } - data, err := ioutil.ReadFile(tokenFile) + data, err := os.ReadFile(tokenFile) if err != nil { return "", err } diff --git a/control-plane/subcommand/get-consul-client-ca/command.go b/control-plane/subcommand/get-consul-client-ca/command.go index 7cbc95a405..a154d778e9 100644 --- a/control-plane/subcommand/get-consul-client-ca/command.go +++ b/control-plane/subcommand/get-consul-client-ca/command.go @@ -4,7 +4,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "strings" "sync" "time" @@ -111,7 +111,7 @@ func (c *Command) Run(args []string) int { return nil }, backoff.NewConstantBackOff(1*time.Second)) - err = ioutil.WriteFile(c.flagOutputFile, []byte(activeRoot), 0644) + err = os.WriteFile(c.flagOutputFile, []byte(activeRoot), 0644) if err != nil { c.UI.Error(fmt.Sprintf("Error writing CA file: %s", err)) return 1 @@ -154,11 +154,11 @@ func (c *Command) consulClient(logger hclog.Logger) (*api.Client, error) { // consulServerAddr returns the consul server address // as a string in the : format. // -// 1. If the server address is a cloud auto-join URL, -// it calls go-discover library to discover server addresses, -// picks the first address from the list and uses the provided port. -// 2. Otherwise, it uses the address provided by the -server-addr -// and the -server-port flags. +// 1. If the server address is a cloud auto-join URL, +// it calls go-discover library to discover server addresses, +// picks the first address from the list and uses the provided port. +// 2. Otherwise, it uses the address provided by the -server-addr +// and the -server-port flags. func (c *Command) consulServerAddr(logger hclog.Logger) (string, error) { // First, check if the server address is a cloud auto-join string. diff --git a/control-plane/subcommand/get-consul-client-ca/command_test.go b/control-plane/subcommand/get-consul-client-ca/command_test.go index 27081149ab..37eecd5434 100644 --- a/control-plane/subcommand/get-consul-client-ca/command_test.go +++ b/control-plane/subcommand/get-consul-client-ca/command_test.go @@ -2,7 +2,6 @@ package getconsulclientca import ( "fmt" - "io/ioutil" "os" "strings" "sync" @@ -75,7 +74,7 @@ func TestRun_FlagsValidation(t *testing.T) { // write it to a file. func TestRun(t *testing.T) { t.Parallel() - outputFile, err := ioutil.TempFile("", "ca") + outputFile, err := os.CreateTemp("", "ca") require.NoError(t, err) defer os.Remove(outputFile.Name()) @@ -128,7 +127,7 @@ func TestRun(t *testing.T) { expectedCARoot := roots.Roots[0].RootCertPEM // read the file contents - actualCARoot, err := ioutil.ReadFile(outputFile.Name()) + actualCARoot, err := os.ReadFile(outputFile.Name()) require.NoError(t, err) require.Equal(t, expectedCARoot, string(actualCARoot)) } @@ -137,7 +136,7 @@ func TestRun(t *testing.T) { // we continue to poll it until it comes up. func TestRun_ConsulServerAvailableLater(t *testing.T) { t.Parallel() - outputFile, err := ioutil.TempFile("", "ca") + outputFile, err := os.CreateTemp("", "ca") require.NoError(t, err) defer os.Remove(outputFile.Name()) @@ -214,7 +213,7 @@ func TestRun_ConsulServerAvailableLater(t *testing.T) { }) // check that the file contents match the actual CA - actualCARoot, err := ioutil.ReadFile(outputFile.Name()) + actualCARoot, err := os.ReadFile(outputFile.Name()) require.NoError(t, err) require.Equal(t, expectedCARoot, string(actualCARoot)) } @@ -224,7 +223,7 @@ func TestRun_ConsulServerAvailableLater(t *testing.T) { // the inactive one. func TestRun_GetsOnlyActiveRoot(t *testing.T) { t.Parallel() - outputFile, err := ioutil.TempFile("", "ca") + outputFile, err := os.CreateTemp("", "ca") require.NoError(t, err) defer os.Remove(outputFile.Name()) @@ -298,7 +297,7 @@ func TestRun_GetsOnlyActiveRoot(t *testing.T) { }) // read the file contents - actualCARoot, err := ioutil.ReadFile(outputFile.Name()) + actualCARoot, err := os.ReadFile(outputFile.Name()) require.NoError(t, err) require.Equal(t, expectedCARoot, string(actualCARoot)) } @@ -307,7 +306,7 @@ func TestRun_GetsOnlyActiveRoot(t *testing.T) { // it uses the provider to get the address of the server. func TestRun_WithProvider(t *testing.T) { t.Parallel() - outputFile, err := ioutil.TempFile("", "ca") + outputFile, err := os.CreateTemp("", "ca") require.NoError(t, err) defer os.Remove(outputFile.Name()) @@ -372,7 +371,7 @@ func TestRun_WithProvider(t *testing.T) { expectedCARoot := roots.Roots[0].RootCertPEM // read the file contents - actualCARoot, err := ioutil.ReadFile(outputFile.Name()) + actualCARoot, err := os.ReadFile(outputFile.Name()) require.NoError(t, err) require.Equal(t, expectedCARoot, string(actualCARoot)) } diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index 008cb8b400..1bf22c78a9 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -5,8 +5,8 @@ import ( "errors" "flag" "fmt" - "io/ioutil" "net/url" + "os" "strconv" "strings" "sync" @@ -345,7 +345,7 @@ func (c *Command) Run(args []string) int { var consulCACert []byte if cfg.TLSConfig.CAFile != "" { var err error - consulCACert, err = ioutil.ReadFile(cfg.TLSConfig.CAFile) + consulCACert, err = os.ReadFile(cfg.TLSConfig.CAFile) if err != nil { c.UI.Error(fmt.Sprintf("error reading Consul's CA cert file %q: %s", cfg.TLSConfig.CAFile, err)) return 1 @@ -545,7 +545,7 @@ func (c *Command) Run(args []string) int { func (c *Command) updateWebhookCABundle(ctx context.Context) error { webhookConfigName := fmt.Sprintf("%s-connect-injector", c.flagResourcePrefix) caPath := fmt.Sprintf("%s/%s", c.flagCertDir, WebhookCAFilename) - caCert, err := ioutil.ReadFile(caPath) + caCert, err := os.ReadFile(caPath) if err != nil { return err } diff --git a/control-plane/subcommand/server-acl-init/command.go b/control-plane/subcommand/server-acl-init/command.go index ddf9b32ba3..af72f325c8 100644 --- a/control-plane/subcommand/server-acl-init/command.go +++ b/control-plane/subcommand/server-acl-init/command.go @@ -5,7 +5,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "regexp" "strings" "sync" @@ -988,7 +988,7 @@ func (c *Command) validateFlags() error { func loadTokenFromFile(tokenFile string) (string, error) { // Load the bootstrap token from file. - tokenBytes, err := ioutil.ReadFile(tokenFile) + tokenBytes, err := os.ReadFile(tokenFile) if err != nil { return "", fmt.Errorf("unable to read token from file %q: %s", tokenFile, err) } diff --git a/control-plane/subcommand/server-acl-init/command_ent_test.go b/control-plane/subcommand/server-acl-init/command_ent_test.go index 3b94a48b0a..27c18f82a4 100644 --- a/control-plane/subcommand/server-acl-init/command_ent_test.go +++ b/control-plane/subcommand/server-acl-init/command_ent_test.go @@ -5,7 +5,6 @@ package serveraclinit import ( "context" "fmt" - "io/ioutil" "net/http" "net/http/httptest" "os" @@ -1216,7 +1215,7 @@ func TestRun_PartitionTokenDefaultPartition_WithProvidedSecretID(t *testing.T) { setUpK8sServiceAccount(t, k8s, ns) partitionToken := "123e4567-e89b-12d3-a456-426614174000" - partitionTokenFile, err := ioutil.TempFile("", "partitiontoken") + partitionTokenFile, err := os.CreateTemp("", "partitiontoken") require.NoError(t, err) defer os.Remove(partitionTokenFile.Name()) diff --git a/control-plane/subcommand/server-acl-init/command_test.go b/control-plane/subcommand/server-acl-init/command_test.go index 71e09fddef..a89fbe2328 100644 --- a/control-plane/subcommand/server-acl-init/command_test.go +++ b/control-plane/subcommand/server-acl-init/command_test.go @@ -5,7 +5,6 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" "math/rand" "net/http" "net/http/httptest" @@ -269,7 +268,7 @@ func TestRun_ReplicationTokenPrimaryDC_WithProvidedSecretID(t *testing.T) { setUpK8sServiceAccount(t, k8s, ns) replicationToken := "123e4567-e89b-12d3-a456-426614174000" - replicationTokenFile, err := ioutil.TempFile("", "replicationtoken") + replicationTokenFile, err := os.CreateTemp("", "replicationtoken") require.NoError(t, err) defer os.Remove(replicationTokenFile.Name()) @@ -524,7 +523,7 @@ func TestRun_AnonymousTokenPolicy(t *testing.T) { k8s, consul, consulHTTPAddr, cleanup = mockReplicatedSetup(t, bootToken) defer cleanup() - tmp, err := ioutil.TempFile("", "") + tmp, err := os.CreateTemp("", "") require.NoError(t, err) _, err = tmp.WriteString(bootToken) require.NoError(t, err) @@ -1560,7 +1559,7 @@ func TestRun_AlreadyBootstrapped(t *testing.T) { require.NoError(t, err) } else { // Write token to a file. - bootTokenFile, err := ioutil.TempFile("", "") + bootTokenFile, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(bootTokenFile.Name()) @@ -1685,7 +1684,7 @@ func TestRun_AlreadyBootstrapped_ServerTokenExists(t *testing.T) { require.NoError(t, err) } else { // Write token to a file. - bootTokenFile, err := ioutil.TempFile("", "") + bootTokenFile, err := os.CreateTemp("", "") require.NoError(t, err) defer os.Remove(bootTokenFile.Name()) diff --git a/control-plane/subcommand/service-address/command.go b/control-plane/subcommand/service-address/command.go index d775b65ba1..91bc600191 100644 --- a/control-plane/subcommand/service-address/command.go +++ b/control-plane/subcommand/service-address/command.go @@ -5,8 +5,8 @@ import ( "errors" "flag" "fmt" - "io/ioutil" "net" + "os" "sync" "time" @@ -143,7 +143,7 @@ func (c *Command) Run(args []string) int { } // Write the address to file. - err = ioutil.WriteFile(c.flagOutputFile, []byte(address), 0600) + err = os.WriteFile(c.flagOutputFile, []byte(address), 0600) if err != nil { c.UI.Error(fmt.Sprintf("Unable to write address to file: %s", err)) return 1 diff --git a/control-plane/subcommand/service-address/command_test.go b/control-plane/subcommand/service-address/command_test.go index 4279f94bd4..24e83551b6 100644 --- a/control-plane/subcommand/service-address/command_test.go +++ b/control-plane/subcommand/service-address/command_test.go @@ -3,7 +3,6 @@ package serviceaddress import ( "context" "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -97,7 +96,7 @@ func TestRun_UnresolvableHostname(t *testing.T) { UI: ui, k8sClient: k8s, } - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(err) defer os.RemoveAll(tmpDir) outputFile := filepath.Join(tmpDir, "address.txt") @@ -198,7 +197,7 @@ func TestRun_ServiceTypes(t *testing.T) { UI: ui, k8sClient: k8s, } - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(err) defer os.RemoveAll(tmpDir) outputFile := filepath.Join(tmpDir, "address.txt") @@ -217,7 +216,7 @@ func TestRun_ServiceTypes(t *testing.T) { require.Contains(ui.ErrorWriter.String(), c.ExpErr) } else { require.Equal(0, responseCode, ui.ErrorWriter.String()) - actAddressBytes, err := ioutil.ReadFile(outputFile) + actAddressBytes, err := os.ReadFile(outputFile) require.NoError(err) require.Equal(c.ExpAddress, string(actAddressBytes)) } @@ -289,7 +288,7 @@ func TestRun_FileWrittenAfterRetry(t *testing.T) { k8sClient: k8s, retryDuration: 10 * time.Millisecond, } - tmpDir, err := ioutil.TempDir("", "") + tmpDir, err := os.MkdirTemp("", "") require.NoError(t, err) defer os.RemoveAll(tmpDir) outputFile := filepath.Join(tmpDir, "address.txt") @@ -300,7 +299,7 @@ func TestRun_FileWrittenAfterRetry(t *testing.T) { "-output-file", outputFile, }) require.Equal(t, 0, responseCode, ui.ErrorWriter.String()) - actAddressBytes, err := ioutil.ReadFile(outputFile) + actAddressBytes, err := os.ReadFile(outputFile) require.NoError(t, err) require.Equal(t, ip, string(actAddressBytes)) }) diff --git a/control-plane/subcommand/tls-init/command.go b/control-plane/subcommand/tls-init/command.go index 7a038b79b2..354a26fdc5 100644 --- a/control-plane/subcommand/tls-init/command.go +++ b/control-plane/subcommand/tls-init/command.go @@ -5,7 +5,7 @@ import ( "errors" "flag" "fmt" - "io/ioutil" + "os" "strings" "sync" "time" @@ -176,13 +176,13 @@ func (c *Command) Run(args []string) int { if c.flagCaFile != "" && c.flagKeyFile != "" { c.log.Info("reading CA certificate from provided file") - caBytes, err = ioutil.ReadFile(c.flagCaFile) + caBytes, err = os.ReadFile(c.flagCaFile) if err != nil { c.log.Error("error reading provided CA file", "err", err) return 1 } c.log.Info("reading CA private key from provided file") - keyBytes, err = ioutil.ReadFile(c.flagKeyFile) + keyBytes, err = os.ReadFile(c.flagKeyFile) if err != nil { c.log.Error("error reading provided private key file", "err", err) return 1 diff --git a/control-plane/subcommand/tls-init/command_test.go b/control-plane/subcommand/tls-init/command_test.go index e22254008a..33493bba16 100644 --- a/control-plane/subcommand/tls-init/command_test.go +++ b/control-plane/subcommand/tls-init/command_test.go @@ -4,7 +4,6 @@ import ( "context" "crypto/x509" "encoding/pem" - "io/ioutil" "net" "os" "testing" @@ -89,16 +88,16 @@ func TestRun_CreatesServerCertificatesWithExistingCAAsFiles(t *testing.T) { k8s := fake.NewSimpleClientset() cmd.clientset = k8s - ca, err := ioutil.TempFile("", "") + ca, err := os.CreateTemp("", "") require.NoError(t, err) defer os.RemoveAll(ca.Name()) - err = ioutil.WriteFile(ca.Name(), []byte(c.caCert), 0644) + err = os.WriteFile(ca.Name(), []byte(c.caCert), 0644) require.NoError(t, err) - key, err := ioutil.TempFile("", "") + key, err := os.CreateTemp("", "") require.NoError(t, err) defer os.RemoveAll(key.Name()) - err = ioutil.WriteFile(key.Name(), []byte(c.caKey), 0644) + err = os.WriteFile(key.Name(), []byte(c.caKey), 0644) require.NoError(t, err) flags := []string{"-name-prefix", "consul", "-ca", ca.Name(), "-key", key.Name()} @@ -152,16 +151,16 @@ func TestRun_UpdatesServerCertificatesWithExistingCertsAsFiles(t *testing.T) { }, metav1.CreateOptions{}) require.NoError(t, err) - ca, err := ioutil.TempFile("", "") + ca, err := os.CreateTemp("", "") require.NoError(t, err) defer os.RemoveAll(ca.Name()) - err = ioutil.WriteFile(ca.Name(), []byte(caCertEC), 0644) + err = os.WriteFile(ca.Name(), []byte(caCertEC), 0644) require.NoError(t, err) - key, err := ioutil.TempFile("", "") + key, err := os.CreateTemp("", "") require.NoError(t, err) defer os.RemoveAll(key.Name()) - err = ioutil.WriteFile(key.Name(), []byte(caKeyEC), 0644) + err = os.WriteFile(key.Name(), []byte(caKeyEC), 0644) require.NoError(t, err) flags := []string{"-name-prefix", "consul", "-ca", ca.Name(), "-key", key.Name(), "-additional-dnsname", "test.dns.name"} diff --git a/control-plane/subcommand/webhook-cert-manager/command.go b/control-plane/subcommand/webhook-cert-manager/command.go index 0c35073dfd..214a1d41e2 100644 --- a/control-plane/subcommand/webhook-cert-manager/command.go +++ b/control-plane/subcommand/webhook-cert-manager/command.go @@ -7,7 +7,6 @@ import ( "errors" "flag" "fmt" - "io/ioutil" "os" "os/signal" "strings" @@ -134,7 +133,7 @@ func (c *Command) Run(args []string) int { } } - configFile, err := ioutil.ReadFile(c.flagConfigFile) + configFile, err := os.ReadFile(c.flagConfigFile) if err != nil { c.UI.Error(fmt.Sprintf("Error reading config file from %s: %s", c.flagConfigFile, err)) return 1 diff --git a/control-plane/subcommand/webhook-cert-manager/command_test.go b/control-plane/subcommand/webhook-cert-manager/command_test.go index 434db47958..1841abf802 100644 --- a/control-plane/subcommand/webhook-cert-manager/command_test.go +++ b/control-plane/subcommand/webhook-cert-manager/command_test.go @@ -2,7 +2,6 @@ package webhookcertmanager import ( "context" - "io/ioutil" "os" "syscall" "testing" @@ -88,7 +87,7 @@ func testSignalHandling(sig os.Signal) func(*testing.T) { } cmd.init() - file, err := ioutil.TempFile("", "config.json") + file, err := os.CreateTemp("", "config.json") require.NoError(t, err) defer os.Remove(file.Name()) @@ -211,7 +210,7 @@ func TestRun_SecretDoesNotExist(t *testing.T) { } cmd.init() - file, err := ioutil.TempFile("", "config.json") + file, err := os.CreateTemp("", "config.json") require.NoError(t, err) defer os.Remove(file.Name()) @@ -339,7 +338,7 @@ func TestRun_SecretExists(t *testing.T) { } cmd.init() - file, err := ioutil.TempFile("", "config.json") + file, err := os.CreateTemp("", "config.json") require.NoError(t, err) defer os.Remove(file.Name()) @@ -439,7 +438,7 @@ func TestRun_SecretUpdates(t *testing.T) { } cmd.init() - file, err := ioutil.TempFile("", "config.json") + file, err := os.CreateTemp("", "config.json") require.NoError(t, err) defer os.Remove(file.Name()) @@ -629,7 +628,7 @@ func TestCertWatcher(t *testing.T) { } cmd.init() - file, err := ioutil.TempFile("", "config.json") + file, err := os.CreateTemp("", "config.json") require.NoError(t, err) defer os.Remove(file.Name()) diff --git a/hack/copy-crds-to-chart/main.go b/hack/copy-crds-to-chart/main.go index efdf2dbf9f..5feee4e229 100644 --- a/hack/copy-crds-to-chart/main.go +++ b/hack/copy-crds-to-chart/main.go @@ -4,7 +4,6 @@ package main import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -35,7 +34,7 @@ func realMain(helmPath string) error { printf("processing %s", filepath.Base(path)) - contentBytes, err := ioutil.ReadFile(path) + contentBytes, err := os.ReadFile(path) if err != nil { return err } @@ -68,7 +67,7 @@ func realMain(helmPath string) error { // Write it. printf("writing to %s", destinationPath) - return ioutil.WriteFile(destinationPath, []byte(contents), 0644) + return os.WriteFile(destinationPath, []byte(contents), 0644) }) } diff --git a/hack/helm-reference-gen/main.go b/hack/helm-reference-gen/main.go index d09c8a8a1c..5f23143caa 100644 --- a/hack/helm-reference-gen/main.go +++ b/hack/helm-reference-gen/main.go @@ -12,7 +12,6 @@ import ( "bytes" "flag" "fmt" - "io/ioutil" "os" "path/filepath" "regexp" @@ -99,7 +98,7 @@ func main() { } // Parse the values.yaml file. - inputBytes, err := ioutil.ReadFile("../../charts/consul/values.yaml") + inputBytes, err := os.ReadFile("../../charts/consul/values.yaml") if err != nil { fmt.Println(err.Error()) os.Exit(1) @@ -118,7 +117,7 @@ func main() { // Otherwise we'll go on to write the changes to the helm docs. helmReferenceFile := filepath.Join(consulRepoPath, "website/content/docs/k8s/helm.mdx") - helmReferenceBytes, err := ioutil.ReadFile(helmReferenceFile) + helmReferenceBytes, err := os.ReadFile(helmReferenceFile) if err != nil { fmt.Println(err.Error()) os.Exit(1) @@ -140,7 +139,7 @@ func main() { } newMdx := helmReferenceContents[0:start+len(startStr)] + out + helmReferenceContents[end:] - err = ioutil.WriteFile(helmReferenceFile, []byte(newMdx), 0644) + err = os.WriteFile(helmReferenceFile, []byte(newMdx), 0644) if err != nil { fmt.Println(err.Error()) os.Exit(1) diff --git a/hack/helm-reference-gen/main_test.go b/hack/helm-reference-gen/main_test.go index 412d221774..03e8648218 100644 --- a/hack/helm-reference-gen/main_test.go +++ b/hack/helm-reference-gen/main_test.go @@ -1,7 +1,7 @@ package main import ( - "io/ioutil" + "os" "path/filepath" "strings" "testing" @@ -493,15 +493,15 @@ key: // Test against a full values file and compare against a golden file. func TestFullValues(t *testing.T) { - inputBytes, err := ioutil.ReadFile(filepath.Join("fixtures", "full-values.yaml")) + inputBytes, err := os.ReadFile(filepath.Join("fixtures", "full-values.yaml")) require.NoError(t, err) - expBytes, err := ioutil.ReadFile(filepath.Join("fixtures", "full-values.golden")) + expBytes, err := os.ReadFile(filepath.Join("fixtures", "full-values.golden")) require.NoError(t, err) actual, err := GenerateDocs(string(inputBytes)) require.NoError(t, err) if actual != string(expBytes) { - require.NoError(t, ioutil.WriteFile(filepath.Join("fixtures", "full-values.actual"), []byte(actual), 0644)) + require.NoError(t, os.WriteFile(filepath.Join("fixtures", "full-values.actual"), []byte(actual), 0644)) require.FailNow(t, "output not equal, actual output to full-values.actual") } } From 2330d0a3eee53f9fc2db538bc4db7501609ec829 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Fri, 26 Aug 2022 11:59:07 -0400 Subject: [PATCH 103/235] CNI Plugin for Consul-k8s (#1456) - Added a CNI installer daemonset to the helm install. On every node, the installer daemonset: - Appends the consul-cni configuration to the main CNI configuration as the final plugin in the CNI chain - Installs the consul-cni binary to the node - Creates a kubeconfig file so that the the consul-cni plugin can communicate with pods. - Repairs the consul-cni configuration if another CNI plugin corrupts the configuration - Added a consul-cni CNI plugin that is executed by the kubelet when a pod is created. - The consul-cni plugin is a chained plugin and must be installed alongside another CNI plugin (eg. calico) - In order to install and use the plugin you must ensure that connect inject (connectInject.enabled = true) and CNI (connectInject.cni.enabled = true) are enabled in the helm chart. - Note: if using consul-cni on GKE, connectInject.cni.cniBinDir must be set to /home/kubernetes/bin - Unit, acceptance, and bats (helm) tests to cover all of the above changes/additions. --- .circleci/config.yml | 315 +- CHANGELOG.md | 2 + Makefile | 32 +- acceptance/framework/config/config.go | 11 + acceptance/framework/config/config_test.go | 11 +- .../cni-kind/custom-resources.yaml | 27 + .../environment/cni-kind/kind.config | 10 + .../environment/cni-kind/tigera-operator.yaml | 18097 ++++++++++++++++ acceptance/framework/flags/flags.go | 13 + acceptance/tests/basic/basic_test.go | 4 + .../tests/consul-dns/consul_dns_test.go | 4 + .../controller/controller_namespaces_test.go | 3 + .../tests/controller/controller_test.go | 4 +- .../tests/partitions/partitions_sync_test.go | 3 + .../snapshot_agent_k8s_secret_test.go | 3 + .../snapshot_agent_vault_test.go | 3 + .../sync/sync_catalog_namespaces_test.go | 3 + acceptance/tests/sync/sync_catalog_test.go | 4 + charts/consul/templates/cni-clusterrole.yaml | 30 + .../templates/cni-clusterrolebinding.yaml | 20 + charts/consul/templates/cni-daemonset.yaml | 83 + .../templates/cni-podsecuritypolicy.yaml | 31 + .../consul/templates/cni-resourcequota.yaml | 22 + .../consul/templates/cni-serviceaccount.yaml | 19 + .../templates/connect-inject-clusterrole.yaml | 10 +- .../templates/connect-inject-deployment.yaml | 1 + charts/consul/test/unit/cni-clusterrole.bats | 31 + .../test/unit/cni-clusterrolebinding.bats | 57 + charts/consul/test/unit/cni-daemonset.bats | 293 + .../test/unit/cni-podsecuritypolicy.bats | 32 + .../consul/test/unit/cni-resourcequota.bats | 57 + .../consul/test/unit/cni-serviceaccount.bats | 53 + .../test/unit/connect-inject-clusterrole.bats | 41 +- .../test/unit/connect-inject-deployment.bats | 30 + charts/consul/values.yaml | 71 +- control-plane/Dockerfile | 8 + .../build-support/functions/20-build.sh | 8 +- .../build-support/scripts/build-local.sh | 1 + control-plane/cni/config/config.go | 42 + control-plane/cni/go.mod | 55 + control-plane/cni/go.sum | 500 + control-plane/cni/main.go | 277 + control-plane/cni/main_test.go | 386 + control-plane/commands.go | 4 + control-plane/connect-inject/annotations.go | 13 +- .../connect-inject/container_init.go | 55 +- .../connect-inject/container_init_test.go | 99 +- .../connect-inject/endpoints_controller.go | 15 +- control-plane/connect-inject/mesh_webhook.go | 35 +- .../connect-inject/mesh_webhook_test.go | 8 +- .../connect-inject/redirect_traffic.go | 115 + .../connect-inject/redirect_traffic_test.go | 447 + control-plane/go.mod | 36 +- control-plane/go.sum | 195 +- .../subcommand/inject-connect/command.go | 6 + .../subcommand/install-cni/binary.go | 56 + .../subcommand/install-cni/binary_test.go | 146 + .../subcommand/install-cni/cniconfig.go | 274 + .../subcommand/install-cni/cniconfig_test.go | 336 + .../subcommand/install-cni/command.go | 281 + .../subcommand/install-cni/command_test.go | 139 + .../subcommand/install-cni/kubeconfig.go | 128 + .../subcommand/install-cni/kubeconfig_test.go | 48 + .../install-cni/testdata/10-calico.conflist | 30 + .../testdata/10-calico.conflist.golden | 51 + .../install-cni/testdata/10-fake-cni.conf | 7 + .../install-cni/testdata/10-kindnet.conflist | 33 + .../10-kindnet.conflist.alreadyinserted | 42 + .../testdata/10-kindnet.conflist.golden | 42 + .../testdata/10-kindnet.conflist.notlast | 42 + .../install-cni/testdata/10-tiny.conflist | 12 + .../testdata/ZZZ-consul-cni-kubeconfig.golden | 18 + .../subcommand/server-acl-init/command.go | 14 +- 73 files changed, 23300 insertions(+), 134 deletions(-) create mode 100644 acceptance/framework/environment/cni-kind/custom-resources.yaml create mode 100644 acceptance/framework/environment/cni-kind/kind.config create mode 100644 acceptance/framework/environment/cni-kind/tigera-operator.yaml create mode 100644 charts/consul/templates/cni-clusterrole.yaml create mode 100644 charts/consul/templates/cni-clusterrolebinding.yaml create mode 100644 charts/consul/templates/cni-daemonset.yaml create mode 100644 charts/consul/templates/cni-podsecuritypolicy.yaml create mode 100644 charts/consul/templates/cni-resourcequota.yaml create mode 100644 charts/consul/templates/cni-serviceaccount.yaml create mode 100644 charts/consul/test/unit/cni-clusterrole.bats create mode 100644 charts/consul/test/unit/cni-clusterrolebinding.bats create mode 100644 charts/consul/test/unit/cni-daemonset.bats create mode 100644 charts/consul/test/unit/cni-podsecuritypolicy.bats create mode 100644 charts/consul/test/unit/cni-resourcequota.bats create mode 100644 charts/consul/test/unit/cni-serviceaccount.bats create mode 100644 control-plane/cni/config/config.go create mode 100644 control-plane/cni/go.mod create mode 100644 control-plane/cni/go.sum create mode 100644 control-plane/cni/main.go create mode 100644 control-plane/cni/main_test.go create mode 100644 control-plane/connect-inject/redirect_traffic.go create mode 100644 control-plane/connect-inject/redirect_traffic_test.go create mode 100644 control-plane/subcommand/install-cni/binary.go create mode 100644 control-plane/subcommand/install-cni/binary_test.go create mode 100644 control-plane/subcommand/install-cni/cniconfig.go create mode 100644 control-plane/subcommand/install-cni/cniconfig_test.go create mode 100644 control-plane/subcommand/install-cni/command.go create mode 100644 control-plane/subcommand/install-cni/command_test.go create mode 100644 control-plane/subcommand/install-cni/kubeconfig.go create mode 100644 control-plane/subcommand/install-cni/kubeconfig_test.go create mode 100644 control-plane/subcommand/install-cni/testdata/10-calico.conflist create mode 100644 control-plane/subcommand/install-cni/testdata/10-calico.conflist.golden create mode 100644 control-plane/subcommand/install-cni/testdata/10-fake-cni.conf create mode 100644 control-plane/subcommand/install-cni/testdata/10-kindnet.conflist create mode 100644 control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.alreadyinserted create mode 100644 control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.golden create mode 100644 control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.notlast create mode 100644 control-plane/subcommand/install-cni/testdata/10-tiny.conflist create mode 100644 control-plane/subcommand/install-cni/testdata/ZZZ-consul-cni-kubeconfig.golden diff --git a/.circleci/config.yml b/.circleci/config.yml index e52b29f000..613e308ff9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,6 +10,7 @@ executors: environment: TEST_RESULTS: /tmp/test-results # path to where test results are saved +slack-channel: &slack-channel CBXF3CGAF control-plane-path: &control-plane-path control-plane cli-path: &cli-path cli acceptance-mod-path: &acceptance-mod-path acceptance @@ -48,7 +49,6 @@ commands: wget https://get.helm.sh/helm-v3.7.0-linux-amd64.tar.gz tar -zxvf helm-v3.7.0-linux-amd64.tar.gz sudo mv linux-amd64/helm /usr/local/bin/helm - create-kind-clusters: parameters: version: @@ -59,6 +59,18 @@ commands: command: | kind create cluster --name dc1 --image kindest/node:<< parameters.version >> kind create cluster --name dc2 --image kindest/node:<< parameters.version >> + create-kind-cni-clusters: + parameters: + version: + type: string + steps: + - run: + name: Create CNI kind clusters + command: | + kind create cluster --config=acceptance/framework/environment/cni-kind/kind.config --name dc1 --image kindest/node:<< parameters.version >> + make kind-cni-calico + kind create cluster --config=acceptance/framework/environment/cni-kind/kind.config --name dc2 --image kindest/node:<< parameters.version >> + make kind-cni-calico run-acceptance-tests: parameters: failfast: @@ -271,9 +283,12 @@ jobs: root: . paths: - control-plane/pkg/bin + - control-plane/cni/pkg/bin # save dev build to CircleCI - store_artifacts: path: ./control-plane/pkg/bin + - store_artifacts: + path: ./control-plane/cni/pkg/bin # upload dev docker image dev-upload-docker: @@ -544,6 +559,38 @@ jobs: - store_artifacts: path: /tmp/test-results + acceptance-tproxy-cni: + environment: + - TEST_RESULTS: /tmp/test-results + machine: + image: ubuntu-2004:202010-01 + resource_class: xlarge + parallelism: 3 + steps: + - checkout + - install-prereqs + - create-kind-clusters: + version: "v1.22.4" + - restore_cache: + keys: + - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + - run: + name: go mod download + working_directory: *acceptance-mod-path + command: go mod download + - save_cache: + key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + paths: + - ~/.go_workspace/pkg/mod + - run: mkdir -p $TEST_RESULTS + - run-acceptance-tests: + failfast: true + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -enable-cni + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + ########################## # CLEANUP CLOUD RESOURCES ########################## @@ -561,6 +608,7 @@ jobs: gcloud container clusters delete $cluster --zone us-central1-a --project ${CLOUDSDK_CORE_PROJECT} --quiet done - slack/status: + channel: *slack-channel fail_only: true failure_message: "GKE cleanup failed" @@ -578,6 +626,7 @@ jobs: az group delete -n $group --yes done - slack/status: + channel: *slack-channel fail_only: true failure_message: "AKS cleanup failed" @@ -597,6 +646,7 @@ jobs: make ci.aws-acceptance-test-cleanup - slack/status: + channel: *slack-channel fail_only: true failure_message: "EKS cleanup failed" @@ -667,9 +717,78 @@ jobs: when: always - slack/status: + channel: *slack-channel fail_only: true failure_message: "GKE acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-gke-cni-1-20: + parallelism: 3 + environment: + - TEST_RESULTS: /tmp/test-results + docker: + # This image is built from test/docker/Test.dockerfile + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + + steps: + - run: + name: Exit if forked PR + command: | + if [ -n "$CIRCLE_PR_NUMBER" ]; then + echo "Skipping acceptance tests for forked PRs; marking step successful." + circleci step halt + fi + + - checkout + + - run: + name: terraform init & apply + working_directory: *gke-terraform-path + command: | + terraform init + echo "${GOOGLE_CREDENTIALS}" | gcloud auth activate-service-account --key-file=- + + # On GKE, we're setting the build number instead of build URL because label values + # cannot contain '/'. + terraform apply \ + -var project=${CLOUDSDK_CORE_PROJECT} \ + -var init_cli=true \ + -var cluster_count=2 \ + -var labels="{\"build_number\": \"$CIRCLE_BUILD_NUM\"}" \ + -auto-approve + + primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) + secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) + + echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV + echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV + + # Restore go module cache if there is one + - restore_cache: + keys: + - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} + + - run: mkdir -p $TEST_RESULTS + + - run-acceptance-tests: + additional-flags: -use-gke -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy -enable-cni + + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + + - run: + name: terraform destroy + working_directory: *gke-terraform-path + command: | + terraform destroy -var project=${CLOUDSDK_CORE_PROJECT} -auto-approve + when: always + + - slack/status: + channel: *slack-channel + fail_only: true + failure_message: "GKE CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-aks-1-21: parallelism: 6 environment: @@ -723,9 +842,66 @@ jobs: when: always - slack/status: + channel: *slack-channel fail_only: true failure_message: "AKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-aks-cni-1-21: + parallelism: 3 + environment: + - TEST_RESULTS: /tmp/test-results + docker: + # This image is built from test/docker/Test.dockerfile + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + + steps: + - checkout + + - run: + name: terraform init & apply + working_directory: *aks-terraform-path + command: | + terraform init + + terraform apply \ + -var client_id="$ARM_CLIENT_ID" \ + -var client_secret="$ARM_CLIENT_SECRET" \ + -var cluster_count=2 \ + -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" \ + -auto-approve + + primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) + secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) + + echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV + echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV + + # Restore go module cache if there is one + - restore_cache: + keys: + - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} + + - run: mkdir -p $TEST_RESULTS + + - run-acceptance-tests: + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni + + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + + - run: + name: terraform destroy + working_directory: *aks-terraform-path + command: | + terraform destroy -auto-approve + when: always + - slack/status: + channel: *slack-channel + fail_only: true + failure_message: "AKS CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-eks-1-19: parallelism: 6 environment: @@ -785,9 +961,73 @@ jobs: when: always - slack/status: + channel: *slack-channel fail_only: true failure_message: "EKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-eks-cni-1-19: + parallelism: 3 + environment: + - TEST_RESULTS: /tmp/test-results + docker: + # This image is built from test/docker/Test.dockerfile + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + + steps: + - checkout + + - run: + name: configure aws + command: | + aws configure --profile helm_user set aws_access_key_id "$AWS_ACCESS_KEY_ID" + aws configure --profile helm_user set aws_secret_access_key "$AWS_SECRET_ACCESS_KEY" + aws configure set role_arn "$AWS_ROLE_ARN" + aws configure set source_profile helm_user + + echo "unset AWS_ACCESS_KEY_ID" >> $BASH_ENV + echo "unset AWS_SECRET_ACCESS_KEY" >> $BASH_ENV + + - run: + name: terraform init & apply + working_directory: *eks-terraform-path + command: | + terraform init + + terraform apply -var cluster_count=2 -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" -auto-approve + + primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) + secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) + + echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV + echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV + + # Restore go module cache if there is one + - restore_cache: + keys: + - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} + + - run: mkdir -p $TEST_RESULTS + + - run-acceptance-tests: + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni + + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + + - run: + name: terraform destroy + working_directory: *eks-terraform-path + command: | + terraform destroy -var cluster_count=2 -auto-approve + when: always + + - slack/status: + channel: *slack-channel + fail_only: true + failure_message: "EKS CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-openshift: environment: TEST_RESULTS: /tmp/test-results @@ -838,6 +1078,7 @@ jobs: when: always - slack/status: + channel: *slack-channel fail_only: true failure_message: "OpenShift acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" @@ -872,9 +1113,45 @@ jobs: - store_artifacts: path: /tmp/test-results - slack/status: + channel: *slack-channel fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-kind-cni-1-23: + parallelism: 3 + environment: + - TEST_RESULTS: /tmp/test-results + machine: + image: ubuntu-2004:202010-01 + resource_class: xlarge + steps: + - checkout + - install-prereqs + - create-kind-cni-clusters: + version: "v1.23.0" + - restore_cache: + keys: + - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + - run: + name: go mod download + working_directory: *acceptance-mod-path + command: go mod download + - save_cache: + key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} + paths: + - ~/.go_workspace/pkg/mod + - run: mkdir -p $TEST_RESULTS + - run-acceptance-tests: + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -enable-cni + - store_test_results: + path: /tmp/test-results + - store_artifacts: + path: /tmp/test-results + - slack/status: + channel: *slack-channel + fail_only: true + failure_message: "Acceptance tests for CNI against Kind with Kubernetes v1.23 failed. Check the logs at: ${CIRCLE_BUILD_URL}" + acceptance-kind-1-23-consul-nightly-1-11: environment: - TEST_RESULTS: /tmp/test-results @@ -909,6 +1186,7 @@ jobs: - store_artifacts: path: /tmp/test-results - slack/status: + channel: *slack-channel fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.11 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" @@ -946,6 +1224,7 @@ jobs: - store_artifacts: path: /tmp/test-results - slack/status: + channel: *slack-channel fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.12 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" @@ -983,6 +1262,7 @@ jobs: - store_artifacts: path: /tmp/test-results - slack/status: + channel: *slack-channel fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.13 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" @@ -990,10 +1270,10 @@ workflows: version: 2 test-and-build: jobs: - # Build this one control-plane binary so that acceptance and acceptance-tproxy will run - # The rest of these CircleCI jobs have been migrated to Github Actions. We need to wait until - # the summer of 2022 for larger puplic Github Action VMs be available before the acceptance tests can - # be moved + # Build this one control-plane binary so that acceptance and acceptance-tproxy will run + # The rest of these CircleCI jobs have been migrated to Github Actions. We need to wait until + # the summer of 2022 for larger puplic Github Action VMs be available before the acceptance tests can + # be moved - build-distro: OS: "linux" ARCH: "amd64 arm64" @@ -1007,6 +1287,10 @@ workflows: context: consul-ci requires: - dev-upload-docker + - acceptance-tproxy-cni: + context: consul-ci + requires: + - dev-upload-docker - acceptance-tproxy: context: consul-ci requires: @@ -1031,24 +1315,39 @@ workflows: - cleanup-azure-resources - cleanup-eks-resources # Disable until we can use UBI images. - # - acceptance-openshift: - # requires: - # - cleanup-azure-resources + # - acceptance-openshift: + # requires: + # - cleanup-azure-resources - acceptance-gke-1-20: requires: - cleanup-gcp-resources - dev-upload-docker + - acceptance-gke-cni-1-20: + requires: + - cleanup-gcp-resources + - dev-upload-docker - acceptance-eks-1-19: requires: - cleanup-eks-resources - dev-upload-docker + - acceptance-eks-cni-1-19: + requires: + - cleanup-eks-resources + - dev-upload-docker - acceptance-aks-1-21: requires: - cleanup-azure-resources - dev-upload-docker + - acceptance-aks-cni-1-21: + requires: + - cleanup-azure-resources + - dev-upload-docker - acceptance-kind-1-23: requires: - dev-upload-docker + - acceptance-kind-cni-1-23: + requires: + - dev-upload-docker nightly-acceptance-tests-consul: triggers: diff --git a/CHANGELOG.md b/CHANGELOG.md index cbf53a1f7e..8f34db1073 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ FEATURES: * MaxInboundConnections in service-defaults CRD * Add support for MaxInboundConnections on the Service Defaults CRD. [[GH-1437](https://github.com/hashicorp/consul-k8s/pull/1437)] +* Consul CNI Plugin + * CNI Plugin for Consul-k8s [[GH-1465](https://github.com/hashicorp/consul-k8s/pull/1456)] IMPROVEMENTS: * CLI: diff --git a/Makefile b/Makefile index 1522dbd442..6edb9b79e3 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ bats-tests: ## Run Helm chart bats tests. # ===========> Control Plane Targets control-plane-dev: ## Build consul-k8s-control-plane binary. - @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o $(GOOS) -a $(GOARCH) + @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a amd64 control-plane-dev-docker: ## Build consul-k8s-control-plane dev Docker image. @$(SHELL) $(CURDIR)/control-plane/build-support/scripts/build-local.sh -o linux -a $(GOARCH) @@ -57,13 +57,23 @@ control-plane-clean: ## Delete bin and pkg dirs. $(CURDIR)/control-plane/bin \ $(CURDIR)/control-plane/pkg -control-plane-lint: ## Run linter in the control-plane directory. +control-plane-lint: cni-plugin-lint ## Run linter in the control-plane directory. cd control-plane; golangci-lint run -c ../.golangci.yml +cni-plugin-lint: + cd control-plane/cni; golangci-lint run -c ../../.golangci.yml + ctrl-generate: get-controller-gen ## Run CRD code generation. cd control-plane; $(CONTROLLER_GEN) object:headerFile="build-support/controller/boilerplate.go.txt" paths="./..." - +# Helper target for doing local cni acceptance testing +kind-cni: + kind delete cluster --name dc1 + kind delete cluster --name dc2 + kind create cluster --config=$(CURDIR)/acceptance/framework/environment/cni-kind/kind.config --name dc1 --image kindest/node:v1.23.6 + make kind-cni-calico + kind create cluster --config=$(CURDIR)/acceptance/framework/environment/cni-kind/kind.config --name dc2 --image kindest/node:v1.23.6 + make kind-cni-calico # ===========> CLI Targets @@ -72,21 +82,28 @@ cli-lint: ## Run linter in the control-plane directory. cd cli; golangci-lint run -c ../.golangci.yml - - # ===========> Acceptance Tests Targets acceptance-lint: ## Run linter in the control-plane directory. cd acceptance; golangci-lint run -c ../.golangci.yml +# For CNI acceptance tests, the calico CNI pluging needs to be installed on Kind. Our consul-cni plugin will not work +# without another plugin installed first +kind-cni-calico: + kubectl create namespace calico-system ||true + kubectl create -f $(CURDIR)/acceptance/framework/environment/cni-kind/tigera-operator.yaml + # Sleeps are needed as installs can happen too quickly for Kind to handle it + @sleep 30 + kubectl create -f $(CURDIR)/acceptance/framework/environment/cni-kind/custom-resources.yaml + @sleep 20 # ===========> Shared Targets help: ## Show targets and their descriptions. @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-38s\033[0m %s\n", $$1, $$2}' -lint: ## Run linter in the control-plane, cli, and acceptance directories. - for p in control-plane cli acceptance; do cd $$p; golangci-lint run --path-prefix $$p -c ../.golangci.yml; cd ..; done +lint: cni-plugin-lint ## Run linter in the control-plane, cli, and acceptance directories. + for p in control-plane cli acceptance; do cd $$p; golangci-lint run --path-prefix $$p -c ../.golangci.yml; cd ..; done ctrl-manifests: get-controller-gen ## Generate CRD manifests. cd control-plane; $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases @@ -132,6 +149,7 @@ SHELL = bash GOOS?=$(shell go env GOOS) GOARCH?=$(shell go env GOARCH) DEV_IMAGE?=consul-k8s-control-plane-dev +DOCKER_HUB_USER=$(shell cat $(HOME)/.dockerhub) GIT_COMMIT?=$(shell git rev-parse --short HEAD) GIT_DIRTY?=$(shell test -n "`git status --porcelain`" && echo "+CHANGES" || true) GIT_DESCRIBE?=$(shell git describe --tags --always) diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index b457f72b5c..f0b50358fe 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -38,6 +38,8 @@ type TestConfig struct { EnablePodSecurityPolicies bool + EnableCNI bool + EnableTransparentProxy bool DisablePeering bool @@ -52,6 +54,7 @@ type TestConfig struct { DebugDirectory string UseKind bool + UseGKE bool helmChartPath string } @@ -84,6 +87,14 @@ func (t *TestConfig) HelmValuesFromConfig() (map[string]string, error) { setIfNotEmpty(helmValues, "global.enablePodSecurityPolicies", "true") } + if t.EnableCNI { + setIfNotEmpty(helmValues, "connectInject.cni.enabled", "true") + // GKE is currently the only cloud provider that uses a different CNI bin dir. + if t.UseGKE { + setIfNotEmpty(helmValues, "connectInject.cni.cniBinDir", "/home/kubernetes/bin") + } + } + setIfNotEmpty(helmValues, "connectInject.transparentProxy.defaultEnabled", strconv.FormatBool(t.EnableTransparentProxy)) setIfNotEmpty(helmValues, "global.image", t.ConsulImage) diff --git a/acceptance/framework/config/config_test.go b/acceptance/framework/config/config_test.go index fb2b129678..28fc48b810 100644 --- a/acceptance/framework/config/config_test.go +++ b/acceptance/framework/config/config_test.go @@ -106,6 +106,16 @@ func TestConfig_HelmValuesFromConfig(t *testing.T) { "connectInject.transparentProxy.defaultEnabled": "true", }, }, + { + "sets connectInject.cni.enabled helm value to true when -enable-cni is set", + TestConfig{ + EnableCNI: true, + }, + map[string]string{ + "connectInject.cni.enabled": "true", + "connectInject.transparentProxy.defaultEnabled": "false", + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -145,7 +155,6 @@ func TestConfig_HelmValuesFromConfig_EntImage(t *testing.T) { } for _, tt := range tests { t.Run(tt.consulImage, func(t *testing.T) { - // Write values.yaml to a temp dir which will then get parsed. valuesYAML := fmt.Sprintf(`global: image: %s diff --git a/acceptance/framework/environment/cni-kind/custom-resources.yaml b/acceptance/framework/environment/cni-kind/custom-resources.yaml new file mode 100644 index 0000000000..1d2e08da56 --- /dev/null +++ b/acceptance/framework/environment/cni-kind/custom-resources.yaml @@ -0,0 +1,27 @@ +# This section includes base Calico installation configuration. +# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.Installation +apiVersion: operator.tigera.io/v1 +kind: Installation +metadata: + name: default +spec: + # Configures Calico networking. + calicoNetwork: + # Note: The ipPools section cannot be modified post-install. + ipPools: + - blockSize: 26 + cidr: 192.168.0.0/16 + encapsulation: VXLANCrossSubnet + natOutgoing: Enabled + nodeSelector: all() + +--- + +# This section configures the Calico API server. +# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.APIServer +apiVersion: operator.tigera.io/v1 +kind: APIServer +metadata: + name: default +spec: {} + diff --git a/acceptance/framework/environment/cni-kind/kind.config b/acceptance/framework/environment/cni-kind/kind.config new file mode 100644 index 0000000000..8f6ec827d1 --- /dev/null +++ b/acceptance/framework/environment/cni-kind/kind.config @@ -0,0 +1,10 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +networking: + # Calicos default subnet. Needed for Calico to run on kind + podSubnet: 192.168.0.0/16 + serviceSubnet: 10.110.0.0/16 + # The default kind.net CNI plugin will not be installed + disableDefaultCNI: true +nodes: +- role: control-plane diff --git a/acceptance/framework/environment/cni-kind/tigera-operator.yaml b/acceptance/framework/environment/cni-kind/tigera-operator.yaml new file mode 100644 index 0000000000..f13e65ceb0 --- /dev/null +++ b/acceptance/framework/environment/cni-kind/tigera-operator.yaml @@ -0,0 +1,18097 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: tigera-operator + labels: + name: tigera-operator +--- +# Source: crds/calico/crd.projectcalico.org_bgpconfigurations.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: bgpconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPConfiguration + listKind: BGPConfigurationList + plural: bgpconfigurations + singular: bgpconfiguration + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: BGPConfiguration contains the configuration for any BGP routing. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BGPConfigurationSpec contains the values of the BGP configuration. + properties: + asNumber: + description: 'ASNumber is the default AS number used by a node. [Default: + 64512]' + format: int32 + type: integer + bindMode: + description: BindMode indicates whether to listen for BGP connections + on all addresses (None) or only on the node's canonical IP address + Node.Spec.BGP.IPvXAddress (NodeIP). Default behaviour is to listen + for BGP connections on all addresses. + type: string + communities: + description: Communities is a list of BGP community values and their + arbitrary names for tagging routes. + items: + description: Community contains standard or large community value + and its name. + properties: + name: + description: Name given to community value. + type: string + value: + description: Value must be of format `aa:nn` or `aa:nn:mm`. + For standard community use `aa:nn` format, where `aa` and + `nn` are 16 bit number. For large community use `aa:nn:mm` + format, where `aa`, `nn` and `mm` are 32 bit number. Where, + `aa` is an AS Number, `nn` and `mm` are per-AS identifier. + pattern: ^(\d+):(\d+)$|^(\d+):(\d+):(\d+)$ + type: string + type: object + type: array + listenPort: + description: ListenPort is the port where BGP protocol should listen. + Defaults to 179 + maximum: 65535 + minimum: 1 + type: integer + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: INFO]' + type: string + nodeMeshMaxRestartTime: + description: Time to allow for software restart for node-to-mesh peerings. When + specified, this is configured as the graceful restart timeout. When + not specified, the BIRD default of 120s is used. This field can + only be set on the default BGPConfiguration instance and requires + that NodeMesh is enabled + type: string + nodeMeshPassword: + description: Optional BGP password for full node-to-mesh peerings. + This field can only be set on the default BGPConfiguration instance + and requires that NodeMesh is enabled + properties: + secretKeyRef: + description: Selects a key of a secret in the node pod's namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + type: object + nodeToNodeMeshEnabled: + description: 'NodeToNodeMeshEnabled sets whether full node to node + BGP mesh is enabled. [Default: true]' + type: boolean + prefixAdvertisements: + description: PrefixAdvertisements contains per-prefix advertisement + configuration. + items: + description: PrefixAdvertisement configures advertisement properties + for the specified CIDR. + properties: + cidr: + description: CIDR for which properties should be advertised. + type: string + communities: + description: Communities can be list of either community names + already defined in `Specs.Communities` or community value + of format `aa:nn` or `aa:nn:mm`. For standard community use + `aa:nn` format, where `aa` and `nn` are 16 bit number. For + large community use `aa:nn:mm` format, where `aa`, `nn` and + `mm` are 32 bit number. Where,`aa` is an AS Number, `nn` and + `mm` are per-AS identifier. + items: + type: string + type: array + type: object + type: array + serviceClusterIPs: + description: ServiceClusterIPs are the CIDR blocks from which service + cluster IPs are allocated. If specified, Calico will advertise these + blocks, as well as any cluster IPs within them. + items: + description: ServiceClusterIPBlock represents a single allowed ClusterIP + CIDR block. + properties: + cidr: + type: string + type: object + type: array + serviceExternalIPs: + description: ServiceExternalIPs are the CIDR blocks for Kubernetes + Service External IPs. Kubernetes Service ExternalIPs will only be + advertised if they are within one of these blocks. + items: + description: ServiceExternalIPBlock represents a single allowed + External IP CIDR block. + properties: + cidr: + type: string + type: object + type: array + serviceLoadBalancerIPs: + description: ServiceLoadBalancerIPs are the CIDR blocks for Kubernetes + Service LoadBalancer IPs. Kubernetes Service status.LoadBalancer.Ingress + IPs will only be advertised if they are within one of these blocks. + items: + description: ServiceLoadBalancerIPBlock represents a single allowed + LoadBalancer IP CIDR block. + properties: + cidr: + type: string + type: object + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_bgppeers.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: bgppeers.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BGPPeer + listKind: BGPPeerList + plural: bgppeers + singular: bgppeer + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BGPPeerSpec contains the specification for a BGPPeer resource. + properties: + asNumber: + description: The AS Number of the peer. + format: int32 + type: integer + keepOriginalNextHop: + description: Option to keep the original nexthop field when routes + are sent to a BGP Peer. Setting "true" configures the selected BGP + Peers node to use the "next hop keep;" instead of "next hop self;"(default) + in the specific branch of the Node on "bird.cfg". + type: boolean + maxRestartTime: + description: Time to allow for software restart. When specified, + this is configured as the graceful restart timeout. When not specified, + the BIRD default of 120s is used. + type: string + node: + description: The node name identifying the Calico node instance that + is targeted by this peer. If this is not set, and no nodeSelector + is specified, then this BGP peer selects all nodes in the cluster. + type: string + nodeSelector: + description: Selector for the nodes that should have this peering. When + this is set, the Node field must be empty. + type: string + numAllowedLocalASNumbers: + description: Maximum number of local AS numbers that are allowed in + the AS path for received routes. This removes BGP loop prevention + and should only be used if absolutely necesssary. + format: int32 + type: integer + password: + description: Optional BGP password for the peerings generated by this + BGPPeer resource. + properties: + secretKeyRef: + description: Selects a key of a secret in the node pod's namespace. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + type: object + peerIP: + description: The IP address of the peer followed by an optional port + number to peer with. If port number is given, format should be `[]:port` + or `:` for IPv4. If optional port number is not set, + and this peer IP and ASNumber belongs to a calico/node with ListenPort + set in BGPConfiguration, then we use that port to peer. + type: string + peerSelector: + description: Selector for the remote nodes to peer with. When this + is set, the PeerIP and ASNumber fields must be empty. For each + peering between the local node and selected remote nodes, we configure + an IPv4 peering if both ends have NodeBGPSpec.IPv4Address specified, + and an IPv6 peering if both ends have NodeBGPSpec.IPv6Address specified. The + remote AS number comes from the remote node's NodeBGPSpec.ASNumber, + or the global default if that is not set. + type: string + sourceAddress: + description: Specifies whether and how to configure a source address + for the peerings generated by this BGPPeer resource. Default value + "UseNodeIP" means to configure the node IP as the source address. "None" + means not to configure a source address. + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_blockaffinities.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: blockaffinities.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: BlockAffinity + listKind: BlockAffinityList + plural: blockaffinities + singular: blockaffinity + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: BlockAffinitySpec contains the specification for a BlockAffinity + resource. + properties: + cidr: + type: string + deleted: + description: Deleted indicates that this block affinity is being deleted. + This field is a string for compatibility with older releases that + mistakenly treat this field as a string. + type: string + node: + type: string + state: + type: string + required: + - cidr + - deleted + - node + - state + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_caliconodestatuses.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: (devel) + creationTimestamp: null + name: caliconodestatuses.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: CalicoNodeStatus + listKind: CalicoNodeStatusList + plural: caliconodestatuses + singular: caliconodestatus + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CalicoNodeStatusSpec contains the specification for a CalicoNodeStatus + resource. + properties: + classes: + description: Classes declares the types of information to monitor + for this calico/node, and allows for selective status reporting + about certain subsets of information. + items: + type: string + type: array + node: + description: The node name identifies the Calico node instance for + node status. + type: string + updatePeriodSeconds: + description: UpdatePeriodSeconds is the period at which CalicoNodeStatus + should be updated. Set to 0 to disable CalicoNodeStatus refresh. + Maximum update period is one day. + format: int32 + type: integer + type: object + status: + description: CalicoNodeStatusStatus defines the observed state of CalicoNodeStatus. + No validation needed for status since it is updated by Calico. + properties: + agent: + description: Agent holds agent status on the node. + properties: + birdV4: + description: BIRDV4 represents the latest observed status of bird4. + properties: + lastBootTime: + description: LastBootTime holds the value of lastBootTime + from bird.ctl output. + type: string + lastReconfigurationTime: + description: LastReconfigurationTime holds the value of lastReconfigTime + from bird.ctl output. + type: string + routerID: + description: Router ID used by bird. + type: string + state: + description: The state of the BGP Daemon. + type: string + version: + description: Version of the BGP daemon + type: string + type: object + birdV6: + description: BIRDV6 represents the latest observed status of bird6. + properties: + lastBootTime: + description: LastBootTime holds the value of lastBootTime + from bird.ctl output. + type: string + lastReconfigurationTime: + description: LastReconfigurationTime holds the value of lastReconfigTime + from bird.ctl output. + type: string + routerID: + description: Router ID used by bird. + type: string + state: + description: The state of the BGP Daemon. + type: string + version: + description: Version of the BGP daemon + type: string + type: object + type: object + bgp: + description: BGP holds node BGP status. + properties: + numberEstablishedV4: + description: The total number of IPv4 established bgp sessions. + type: integer + numberEstablishedV6: + description: The total number of IPv6 established bgp sessions. + type: integer + numberNotEstablishedV4: + description: The total number of IPv4 non-established bgp sessions. + type: integer + numberNotEstablishedV6: + description: The total number of IPv6 non-established bgp sessions. + type: integer + peersV4: + description: PeersV4 represents IPv4 BGP peers status on the node. + items: + description: CalicoNodePeer contains the status of BGP peers + on the node. + properties: + peerIP: + description: IP address of the peer whose condition we are + reporting. + type: string + since: + description: Since the state or reason last changed. + type: string + state: + description: State is the BGP session state. + type: string + type: + description: Type indicates whether this peer is configured + via the node-to-node mesh, or via en explicit global or + per-node BGPPeer object. + type: string + type: object + type: array + peersV6: + description: PeersV6 represents IPv6 BGP peers status on the node. + items: + description: CalicoNodePeer contains the status of BGP peers + on the node. + properties: + peerIP: + description: IP address of the peer whose condition we are + reporting. + type: string + since: + description: Since the state or reason last changed. + type: string + state: + description: State is the BGP session state. + type: string + type: + description: Type indicates whether this peer is configured + via the node-to-node mesh, or via en explicit global or + per-node BGPPeer object. + type: string + type: object + type: array + required: + - numberEstablishedV4 + - numberEstablishedV6 + - numberNotEstablishedV4 + - numberNotEstablishedV6 + type: object + lastUpdated: + description: LastUpdated is a timestamp representing the server time + when CalicoNodeStatus object last updated. It is represented in + RFC3339 form and is in UTC. + format: date-time + nullable: true + type: string + routes: + description: Routes reports routes known to the Calico BGP daemon + on the node. + properties: + routesV4: + description: RoutesV4 represents IPv4 routes on the node. + items: + description: CalicoNodeRoute contains the status of BGP routes + on the node. + properties: + destination: + description: Destination of the route. + type: string + gateway: + description: Gateway for the destination. + type: string + interface: + description: Interface for the destination + type: string + learnedFrom: + description: LearnedFrom contains information regarding + where this route originated. + properties: + peerIP: + description: If sourceType is NodeMesh or BGPPeer, IP + address of the router that sent us this route. + type: string + sourceType: + description: Type of the source where a route is learned + from. + type: string + type: object + type: + description: Type indicates if the route is being used for + forwarding or not. + type: string + type: object + type: array + routesV6: + description: RoutesV6 represents IPv6 routes on the node. + items: + description: CalicoNodeRoute contains the status of BGP routes + on the node. + properties: + destination: + description: Destination of the route. + type: string + gateway: + description: Gateway for the destination. + type: string + interface: + description: Interface for the destination + type: string + learnedFrom: + description: LearnedFrom contains information regarding + where this route originated. + properties: + peerIP: + description: If sourceType is NodeMesh or BGPPeer, IP + address of the router that sent us this route. + type: string + sourceType: + description: Type of the source where a route is learned + from. + type: string + type: object + type: + description: Type indicates if the route is being used for + forwarding or not. + type: string + type: object + type: array + type: object + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_clusterinformations.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: clusterinformations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: ClusterInformation + listKind: ClusterInformationList + plural: clusterinformations + singular: clusterinformation + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ClusterInformation contains the cluster specific information. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterInformationSpec contains the values of describing + the cluster. + properties: + calicoVersion: + description: CalicoVersion is the version of Calico that the cluster + is running + type: string + clusterGUID: + description: ClusterGUID is the GUID of the cluster + type: string + clusterType: + description: ClusterType describes the type of the cluster + type: string + datastoreReady: + description: DatastoreReady is used during significant datastore migrations + to signal to components such as Felix that it should wait before + accessing the datastore. + type: boolean + variant: + description: Variant declares which variant of Calico should be active. + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_felixconfigurations.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: felixconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: FelixConfiguration + listKind: FelixConfigurationList + plural: felixconfigurations + singular: felixconfiguration + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Felix Configuration contains the configuration for Felix. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: FelixConfigurationSpec contains the values of the Felix configuration. + properties: + allowIPIPPacketsFromWorkloads: + description: 'AllowIPIPPacketsFromWorkloads controls whether Felix + will add a rule to drop IPIP encapsulated traffic from workloads + [Default: false]' + type: boolean + allowVXLANPacketsFromWorkloads: + description: 'AllowVXLANPacketsFromWorkloads controls whether Felix + will add a rule to drop VXLAN encapsulated traffic from workloads + [Default: false]' + type: boolean + awsSrcDstCheck: + description: 'Set source-destination-check on AWS EC2 instances. Accepted + value must be one of "DoNothing", "Enable" or "Disable". [Default: + DoNothing]' + enum: + - DoNothing + - Enable + - Disable + type: string + bpfConnectTimeLoadBalancingEnabled: + description: 'BPFConnectTimeLoadBalancingEnabled when in BPF mode, + controls whether Felix installs the connection-time load balancer. The + connect-time load balancer is required for the host to be able to + reach Kubernetes services and it improves the performance of pod-to-service + connections. The only reason to disable it is for debugging purposes. [Default: + true]' + type: boolean + bpfDataIfacePattern: + description: BPFDataIfacePattern is a regular expression that controls + which interfaces Felix should attach BPF programs to in order to + catch traffic to/from the network. This needs to match the interfaces + that Calico workload traffic flows over as well as any interfaces + that handle incoming traffic to nodeports and services from outside + the cluster. It should not match the workload interfaces (usually + named cali...). + type: string + bpfDisableUnprivileged: + description: 'BPFDisableUnprivileged, if enabled, Felix sets the kernel.unprivileged_bpf_disabled + sysctl to disable unprivileged use of BPF. This ensures that unprivileged + users cannot access Calico''s BPF maps and cannot insert their own + BPF programs to interfere with Calico''s. [Default: true]' + type: boolean + bpfEnabled: + description: 'BPFEnabled, if enabled Felix will use the BPF dataplane. + [Default: false]' + type: boolean + bpfEnforceRPF: + description: 'BPFEnforceRPF enforce strict RPF on all interfaces with + BPF programs regardless of what is the per-interfaces or global + setting. Possible values are Disabled or Strict. [Default: Strict]' + type: string + bpfExtToServiceConnmark: + description: 'BPFExtToServiceConnmark in BPF mode, control a 32bit + mark that is set on connections from an external client to a local + service. This mark allows us to control how packets of that connection + are routed within the host and how is routing interpreted by RPF + check. [Default: 0]' + type: integer + bpfExternalServiceMode: + description: 'BPFExternalServiceMode in BPF mode, controls how connections + from outside the cluster to services (node ports and cluster IPs) + are forwarded to remote workloads. If set to "Tunnel" then both + request and response traffic is tunneled to the remote node. If + set to "DSR", the request traffic is tunneled but the response traffic + is sent directly from the remote node. In "DSR" mode, the remote + node appears to use the IP of the ingress node; this requires a + permissive L2 network. [Default: Tunnel]' + type: string + bpfKubeProxyEndpointSlicesEnabled: + description: BPFKubeProxyEndpointSlicesEnabled in BPF mode, controls + whether Felix's embedded kube-proxy accepts EndpointSlices or not. + type: boolean + bpfKubeProxyIptablesCleanupEnabled: + description: 'BPFKubeProxyIptablesCleanupEnabled, if enabled in BPF + mode, Felix will proactively clean up the upstream Kubernetes kube-proxy''s + iptables chains. Should only be enabled if kube-proxy is not running. [Default: + true]' + type: boolean + bpfKubeProxyMinSyncPeriod: + description: 'BPFKubeProxyMinSyncPeriod, in BPF mode, controls the + minimum time between updates to the dataplane for Felix''s embedded + kube-proxy. Lower values give reduced set-up latency. Higher values + reduce Felix CPU usage by batching up more work. [Default: 1s]' + type: string + bpfLogLevel: + description: 'BPFLogLevel controls the log level of the BPF programs + when in BPF dataplane mode. One of "Off", "Info", or "Debug". The + logs are emitted to the BPF trace pipe, accessible with the command + `tc exec bpf debug`. [Default: Off].' + type: string + bpfMapSizeConntrack: + description: 'BPFMapSizeConntrack sets the size for the conntrack + map. This map must be large enough to hold an entry for each active + connection. Warning: changing the size of the conntrack map can + cause disruption.' + type: integer + bpfMapSizeIPSets: + description: BPFMapSizeIPSets sets the size for ipsets map. The IP + sets map must be large enough to hold an entry for each endpoint + matched by every selector in the source/destination matches in network + policy. Selectors such as "all()" can result in large numbers of + entries (one entry per endpoint in that case). + type: integer + bpfMapSizeIfState: + description: BPFMapSizeIfState sets the size for ifstate map. The + ifstate map must be large enough to hold an entry for each device + (host + workloads) on a host. + type: integer + bpfMapSizeNATAffinity: + type: integer + bpfMapSizeNATBackend: + description: BPFMapSizeNATBackend sets the size for nat back end map. + This is the total number of endpoints. This is mostly more than + the size of the number of services. + type: integer + bpfMapSizeNATFrontend: + description: BPFMapSizeNATFrontend sets the size for nat front end + map. FrontendMap should be large enough to hold an entry for each + nodeport, external IP and each port in each service. + type: integer + bpfMapSizeRoute: + description: BPFMapSizeRoute sets the size for the routes map. The + routes map should be large enough to hold one entry per workload + and a handful of entries per host (enough to cover its own IPs and + tunnel IPs). + type: integer + bpfPSNATPorts: + anyOf: + - type: integer + - type: string + description: 'BPFPSNATPorts sets the range from which we randomly + pick a port if there is a source port collision. This should be + within the ephemeral range as defined by RFC 6056 (1024–65535) and + preferably outside the ephemeral ranges used by common operating + systems. Linux uses 32768–60999, while others mostly use the IANA + defined range 49152–65535. It is not necessarily a problem if this + range overlaps with the operating systems. Both ends of the range + are inclusive. [Default: 20000:29999]' + pattern: ^.* + x-kubernetes-int-or-string: true + bpfPolicyDebugEnabled: + description: BPFPolicyDebugEnabled when true, Felix records detailed + information about the BPF policy programs, which can be examined + with the calico-bpf command-line tool. + type: boolean + chainInsertMode: + description: 'ChainInsertMode controls whether Felix hooks the kernel''s + top-level iptables chains by inserting a rule at the top of the + chain or by appending a rule at the bottom. insert is the safe default + since it prevents Calico''s rules from being bypassed. If you switch + to append mode, be sure that the other rules in the chains signal + acceptance by falling through to the Calico rules, otherwise the + Calico policy will be bypassed. [Default: insert]' + type: string + dataplaneDriver: + description: DataplaneDriver filename of the external dataplane driver + to use. Only used if UseInternalDataplaneDriver is set to false. + type: string + dataplaneWatchdogTimeout: + description: 'DataplaneWatchdogTimeout is the readiness/liveness timeout + used for Felix''s (internal) dataplane driver. Increase this value + if you experience spurious non-ready or non-live events when Felix + is under heavy load. Decrease the value to get felix to report non-live + or non-ready more quickly. [Default: 90s]' + type: string + debugDisableLogDropping: + type: boolean + debugMemoryProfilePath: + type: string + debugSimulateCalcGraphHangAfter: + type: string + debugSimulateDataplaneHangAfter: + type: string + defaultEndpointToHostAction: + description: 'DefaultEndpointToHostAction controls what happens to + traffic that goes from a workload endpoint to the host itself (after + the traffic hits the endpoint egress policy). By default Calico + blocks traffic from workload endpoints to the host itself with an + iptables "DROP" action. If you want to allow some or all traffic + from endpoint to host, set this parameter to RETURN or ACCEPT. Use + RETURN if you have your own rules in the iptables "INPUT" chain; + Calico will insert its rules at the top of that chain, then "RETURN" + packets to the "INPUT" chain once it has completed processing workload + endpoint egress policy. Use ACCEPT to unconditionally accept packets + from workloads after processing workload endpoint egress policy. + [Default: Drop]' + type: string + deviceRouteProtocol: + description: This defines the route protocol added to programmed device + routes, by default this will be RTPROT_BOOT when left blank. + type: integer + deviceRouteSourceAddress: + description: This is the IPv4 source address to use on programmed + device routes. By default the source address is left blank, leaving + the kernel to choose the source address used. + type: string + deviceRouteSourceAddressIPv6: + description: This is the IPv6 source address to use on programmed + device routes. By default the source address is left blank, leaving + the kernel to choose the source address used. + type: string + disableConntrackInvalidCheck: + type: boolean + endpointReportingDelay: + type: string + endpointReportingEnabled: + type: boolean + externalNodesList: + description: ExternalNodesCIDRList is a list of CIDR's of external-non-calico-nodes + which may source tunnel traffic and have the tunneled traffic be + accepted at calico nodes. + items: + type: string + type: array + failsafeInboundHostPorts: + description: 'FailsafeInboundHostPorts is a list of UDP/TCP ports + and CIDRs that Felix will allow incoming traffic to host endpoints + on irrespective of the security policy. This is useful to avoid + accidentally cutting off a host with incorrect configuration. For + back-compatibility, if the protocol is not specified, it defaults + to "tcp". If a CIDR is not specified, it will allow traffic from + all addresses. To disable all inbound host ports, use the value + none. The default value allows ssh access and DHCP. [Default: tcp:22, + udp:68, tcp:179, tcp:2379, tcp:2380, tcp:6443, tcp:6666, tcp:6667]' + items: + description: ProtoPort is combination of protocol, port, and CIDR. + Protocol and port must be specified. + properties: + net: + type: string + port: + type: integer + protocol: + type: string + required: + - port + - protocol + type: object + type: array + failsafeOutboundHostPorts: + description: 'FailsafeOutboundHostPorts is a list of UDP/TCP ports + and CIDRs that Felix will allow outgoing traffic from host endpoints + to irrespective of the security policy. This is useful to avoid + accidentally cutting off a host with incorrect configuration. For + back-compatibility, if the protocol is not specified, it defaults + to "tcp". If a CIDR is not specified, it will allow traffic from + all addresses. To disable all outbound host ports, use the value + none. The default value opens etcd''s standard ports to ensure that + Felix does not get cut off from etcd as well as allowing DHCP and + DNS. [Default: tcp:179, tcp:2379, tcp:2380, tcp:6443, tcp:6666, + tcp:6667, udp:53, udp:67]' + items: + description: ProtoPort is combination of protocol, port, and CIDR. + Protocol and port must be specified. + properties: + net: + type: string + port: + type: integer + protocol: + type: string + required: + - port + - protocol + type: object + type: array + featureDetectOverride: + description: FeatureDetectOverride is used to override the feature + detection. Values are specified in a comma separated list with no + spaces, example; "SNATFullyRandom=true,MASQFullyRandom=false,RestoreSupportsLock=". + "true" or "false" will force the feature, empty or omitted values + are auto-detected. + type: string + floatingIPs: + description: FloatingIPs configures whether or not Felix will program + floating IP addresses. + enum: + - Enabled + - Disabled + type: string + genericXDPEnabled: + description: 'GenericXDPEnabled enables Generic XDP so network cards + that don''t support XDP offload or driver modes can use XDP. This + is not recommended since it doesn''t provide better performance + than iptables. [Default: false]' + type: boolean + healthEnabled: + type: boolean + healthHost: + type: string + healthPort: + type: integer + interfaceExclude: + description: 'InterfaceExclude is a comma-separated list of interfaces + that Felix should exclude when monitoring for host endpoints. The + default value ensures that Felix ignores Kubernetes'' IPVS dummy + interface, which is used internally by kube-proxy. If you want to + exclude multiple interface names using a single value, the list + supports regular expressions. For regular expressions you must wrap + the value with ''/''. For example having values ''/^kube/,veth1'' + will exclude all interfaces that begin with ''kube'' and also the + interface ''veth1''. [Default: kube-ipvs0]' + type: string + interfacePrefix: + description: 'InterfacePrefix is the interface name prefix that identifies + workload endpoints and so distinguishes them from host endpoint + interfaces. Note: in environments other than bare metal, the orchestrators + configure this appropriately. For example our Kubernetes and Docker + integrations set the ''cali'' value, and our OpenStack integration + sets the ''tap'' value. [Default: cali]' + type: string + interfaceRefreshInterval: + description: InterfaceRefreshInterval is the period at which Felix + rescans local interfaces to verify their state. The rescan can be + disabled by setting the interval to 0. + type: string + ipipEnabled: + description: 'IPIPEnabled overrides whether Felix should configure + an IPIP interface on the host. Optional as Felix determines this + based on the existing IP pools. [Default: nil (unset)]' + type: boolean + ipipMTU: + description: 'IPIPMTU is the MTU to set on the tunnel device. See + Configuring MTU [Default: 1440]' + type: integer + ipsetsRefreshInterval: + description: 'IpsetsRefreshInterval is the period at which Felix re-checks + all iptables state to ensure that no other process has accidentally + broken Calico''s rules. Set to 0 to disable iptables refresh. [Default: + 90s]' + type: string + iptablesBackend: + description: IptablesBackend specifies which backend of iptables will + be used. The default is legacy. + type: string + iptablesFilterAllowAction: + type: string + iptablesLockFilePath: + description: 'IptablesLockFilePath is the location of the iptables + lock file. You may need to change this if the lock file is not in + its standard location (for example if you have mapped it into Felix''s + container at a different path). [Default: /run/xtables.lock]' + type: string + iptablesLockProbeInterval: + description: 'IptablesLockProbeInterval is the time that Felix will + wait between attempts to acquire the iptables lock if it is not + available. Lower values make Felix more responsive when the lock + is contended, but use more CPU. [Default: 50ms]' + type: string + iptablesLockTimeout: + description: 'IptablesLockTimeout is the time that Felix will wait + for the iptables lock, or 0, to disable. To use this feature, Felix + must share the iptables lock file with all other processes that + also take the lock. When running Felix inside a container, this + requires the /run directory of the host to be mounted into the calico/node + or calico/felix container. [Default: 0s disabled]' + type: string + iptablesMangleAllowAction: + type: string + iptablesMarkMask: + description: 'IptablesMarkMask is the mask that Felix selects its + IPTables Mark bits from. Should be a 32 bit hexadecimal number with + at least 8 bits set, none of which clash with any other mark bits + in use on the system. [Default: 0xff000000]' + format: int32 + type: integer + iptablesNATOutgoingInterfaceFilter: + type: string + iptablesPostWriteCheckInterval: + description: 'IptablesPostWriteCheckInterval is the period after Felix + has done a write to the dataplane that it schedules an extra read + back in order to check the write was not clobbered by another process. + This should only occur if another application on the system doesn''t + respect the iptables lock. [Default: 1s]' + type: string + iptablesRefreshInterval: + description: 'IptablesRefreshInterval is the period at which Felix + re-checks the IP sets in the dataplane to ensure that no other process + has accidentally broken Calico''s rules. Set to 0 to disable IP + sets refresh. Note: the default for this value is lower than the + other refresh intervals as a workaround for a Linux kernel bug that + was fixed in kernel version 4.11. If you are using v4.11 or greater + you may want to set this to, a higher value to reduce Felix CPU + usage. [Default: 10s]' + type: string + ipv6Support: + description: IPv6Support controls whether Felix enables support for + IPv6 (if supported by the in-use dataplane). + type: boolean + kubeNodePortRanges: + description: 'KubeNodePortRanges holds list of port ranges used for + service node ports. Only used if felix detects kube-proxy running + in ipvs mode. Felix uses these ranges to separate host and workload + traffic. [Default: 30000:32767].' + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + logDebugFilenameRegex: + description: LogDebugFilenameRegex controls which source code files + have their Debug log output included in the logs. Only logs from + files with names that match the given regular expression are included. The + filter only applies to Debug level logs. + type: string + logFilePath: + description: 'LogFilePath is the full path to the Felix log. Set to + none to disable file logging. [Default: /var/log/calico/felix.log]' + type: string + logPrefix: + description: 'LogPrefix is the log prefix that Felix uses when rendering + LOG rules. [Default: calico-packet]' + type: string + logSeverityFile: + description: 'LogSeverityFile is the log severity above which logs + are sent to the log file. [Default: Info]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: Info]' + type: string + logSeveritySys: + description: 'LogSeveritySys is the log severity above which logs + are sent to the syslog. Set to None for no logging to syslog. [Default: + Info]' + type: string + maxIpsetSize: + type: integer + metadataAddr: + description: 'MetadataAddr is the IP address or domain name of the + server that can answer VM queries for cloud-init metadata. In OpenStack, + this corresponds to the machine running nova-api (or in Ubuntu, + nova-api-metadata). A value of none (case insensitive) means that + Felix should not set up any NAT rule for the metadata path. [Default: + 127.0.0.1]' + type: string + metadataPort: + description: 'MetadataPort is the port of the metadata server. This, + combined with global.MetadataAddr (if not ''None''), is used to + set up a NAT rule, from 169.254.169.254:80 to MetadataAddr:MetadataPort. + In most cases this should not need to be changed [Default: 8775].' + type: integer + mtuIfacePattern: + description: MTUIfacePattern is a regular expression that controls + which interfaces Felix should scan in order to calculate the host's + MTU. This should not match workload interfaces (usually named cali...). + type: string + natOutgoingAddress: + description: NATOutgoingAddress specifies an address to use when performing + source NAT for traffic in a natOutgoing pool that is leaving the + network. By default the address used is an address on the interface + the traffic is leaving on (ie it uses the iptables MASQUERADE target) + type: string + natPortRange: + anyOf: + - type: integer + - type: string + description: NATPortRange specifies the range of ports that is used + for port mapping when doing outgoing NAT. When unset the default + behavior of the network stack is used. + pattern: ^.* + x-kubernetes-int-or-string: true + netlinkTimeout: + type: string + openstackRegion: + description: 'OpenstackRegion is the name of the region that a particular + Felix belongs to. In a multi-region Calico/OpenStack deployment, + this must be configured somehow for each Felix (here in the datamodel, + or in felix.cfg or the environment on each compute node), and must + match the [calico] openstack_region value configured in neutron.conf + on each node. [Default: Empty]' + type: string + policySyncPathPrefix: + description: 'PolicySyncPathPrefix is used to by Felix to communicate + policy changes to external services, like Application layer policy. + [Default: Empty]' + type: string + prometheusGoMetricsEnabled: + description: 'PrometheusGoMetricsEnabled disables Go runtime metrics + collection, which the Prometheus client does by default, when set + to false. This reduces the number of metrics reported, reducing + Prometheus load. [Default: true]' + type: boolean + prometheusMetricsEnabled: + description: 'PrometheusMetricsEnabled enables the Prometheus metrics + server in Felix if set to true. [Default: false]' + type: boolean + prometheusMetricsHost: + description: 'PrometheusMetricsHost is the host that the Prometheus + metrics server should bind to. [Default: empty]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. [Default: 9091]' + type: integer + prometheusProcessMetricsEnabled: + description: 'PrometheusProcessMetricsEnabled disables process metrics + collection, which the Prometheus client does by default, when set + to false. This reduces the number of metrics reported, reducing + Prometheus load. [Default: true]' + type: boolean + prometheusWireGuardMetricsEnabled: + description: 'PrometheusWireGuardMetricsEnabled disables wireguard + metrics collection, which the Prometheus client does by default, + when set to false. This reduces the number of metrics reported, + reducing Prometheus load. [Default: true]' + type: boolean + removeExternalRoutes: + description: Whether or not to remove device routes that have not + been programmed by Felix. Disabling this will allow external applications + to also add device routes. This is enabled by default which means + we will remove externally added routes. + type: boolean + reportingInterval: + description: 'ReportingInterval is the interval at which Felix reports + its status into the datastore or 0 to disable. Must be non-zero + in OpenStack deployments. [Default: 30s]' + type: string + reportingTTL: + description: 'ReportingTTL is the time-to-live setting for process-wide + status reports. [Default: 90s]' + type: string + routeRefreshInterval: + description: 'RouteRefreshInterval is the period at which Felix re-checks + the routes in the dataplane to ensure that no other process has + accidentally broken Calico''s rules. Set to 0 to disable route refresh. + [Default: 90s]' + type: string + routeSource: + description: 'RouteSource configures where Felix gets its routing + information. - WorkloadIPs: use workload endpoints to construct + routes. - CalicoIPAM: the default - use IPAM data to construct routes.' + type: string + routeSyncDisabled: + description: RouteSyncDisabled will disable all operations performed + on the route table. Set to true to run in network-policy mode only. + type: boolean + routeTableRange: + description: Deprecated in favor of RouteTableRanges. Calico programs + additional Linux route tables for various purposes. RouteTableRange + specifies the indices of the route tables that Calico should use. + properties: + max: + type: integer + min: + type: integer + required: + - max + - min + type: object + routeTableRanges: + description: Calico programs additional Linux route tables for various + purposes. RouteTableRanges specifies a set of table index ranges + that Calico should use. Deprecates`RouteTableRange`, overrides `RouteTableRange`. + items: + properties: + max: + type: integer + min: + type: integer + required: + - max + - min + type: object + type: array + serviceLoopPrevention: + description: 'When service IP advertisement is enabled, prevent routing + loops to service IPs that are not in use, by dropping or rejecting + packets that do not get DNAT''d by kube-proxy. Unless set to "Disabled", + in which case such routing loops continue to be allowed. [Default: + Drop]' + type: string + sidecarAccelerationEnabled: + description: 'SidecarAccelerationEnabled enables experimental sidecar + acceleration [Default: false]' + type: boolean + usageReportingEnabled: + description: 'UsageReportingEnabled reports anonymous Calico version + number and cluster size to projectcalico.org. Logs warnings returned + by the usage server. For example, if a significant security vulnerability + has been discovered in the version of Calico being used. [Default: + true]' + type: boolean + usageReportingInitialDelay: + description: 'UsageReportingInitialDelay controls the minimum delay + before Felix makes a report. [Default: 300s]' + type: string + usageReportingInterval: + description: 'UsageReportingInterval controls the interval at which + Felix makes reports. [Default: 86400s]' + type: string + useInternalDataplaneDriver: + description: UseInternalDataplaneDriver, if true, Felix will use its + internal dataplane programming logic. If false, it will launch + an external dataplane driver and communicate with it over protobuf. + type: boolean + vxlanEnabled: + description: 'VXLANEnabled overrides whether Felix should create the + VXLAN tunnel device for VXLAN networking. Optional as Felix determines + this based on the existing IP pools. [Default: nil (unset)]' + type: boolean + vxlanMTU: + description: 'VXLANMTU is the MTU to set on the IPv4 VXLAN tunnel + device. See Configuring MTU [Default: 1410]' + type: integer + vxlanMTUV6: + description: 'VXLANMTUV6 is the MTU to set on the IPv6 VXLAN tunnel + device. See Configuring MTU [Default: 1390]' + type: integer + vxlanPort: + type: integer + vxlanVNI: + type: integer + wireguardEnabled: + description: 'WireguardEnabled controls whether Wireguard is enabled + for IPv4 (encapsulating IPv4 traffic over an IPv4 underlay network). + [Default: false]' + type: boolean + wireguardEnabledV6: + description: 'WireguardEnabledV6 controls whether Wireguard is enabled + for IPv6 (encapsulating IPv6 traffic over an IPv6 underlay network). + [Default: false]' + type: boolean + wireguardHostEncryptionEnabled: + description: 'WireguardHostEncryptionEnabled controls whether Wireguard + host-to-host encryption is enabled. [Default: false]' + type: boolean + wireguardInterfaceName: + description: 'WireguardInterfaceName specifies the name to use for + the IPv4 Wireguard interface. [Default: wireguard.cali]' + type: string + wireguardInterfaceNameV6: + description: 'WireguardInterfaceNameV6 specifies the name to use for + the IPv6 Wireguard interface. [Default: wg-v6.cali]' + type: string + wireguardKeepAlive: + description: 'WireguardKeepAlive controls Wireguard PersistentKeepalive + option. Set 0 to disable. [Default: 0]' + type: string + wireguardListeningPort: + description: 'WireguardListeningPort controls the listening port used + by IPv4 Wireguard. [Default: 51820]' + type: integer + wireguardListeningPortV6: + description: 'WireguardListeningPortV6 controls the listening port + used by IPv6 Wireguard. [Default: 51821]' + type: integer + wireguardMTU: + description: 'WireguardMTU controls the MTU on the IPv4 Wireguard + interface. See Configuring MTU [Default: 1440]' + type: integer + wireguardMTUV6: + description: 'WireguardMTUV6 controls the MTU on the IPv6 Wireguard + interface. See Configuring MTU [Default: 1420]' + type: integer + wireguardRoutingRulePriority: + description: 'WireguardRoutingRulePriority controls the priority value + to use for the Wireguard routing rule. [Default: 99]' + type: integer + workloadSourceSpoofing: + description: WorkloadSourceSpoofing controls whether pods can use + the allowedSourcePrefixes annotation to send traffic with a source + IP address that is not theirs. This is disabled by default. When + set to "Any", pods can request any prefix. + type: string + xdpEnabled: + description: 'XDPEnabled enables XDP acceleration for suitable untracked + incoming deny rules. [Default: true]' + type: boolean + xdpRefreshInterval: + description: 'XDPRefreshInterval is the period at which Felix re-checks + all XDP state to ensure that no other process has accidentally broken + Calico''s BPF maps or attached programs. Set to 0 to disable XDP + refresh. [Default: 90s]' + type: string + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_globalnetworkpolicies.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: globalnetworkpolicies.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: GlobalNetworkPolicy + listKind: GlobalNetworkPolicyList + plural: globalnetworkpolicies + singular: globalnetworkpolicy + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + applyOnForward: + description: ApplyOnForward indicates to apply the rules in this policy + on forward traffic. + type: boolean + doNotTrack: + description: DoNotTrack indicates whether packets matched by the rules + in this policy should go through the data plane's connection tracking, + such as Linux conntrack. If True, the rules in this policy are + applied before any data plane connection tracking, and packets allowed + by this policy are marked as not to be tracked. + type: boolean + egress: + description: The ordered set of egress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + ingress: + description: The ordered set of ingress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + namespaceSelector: + description: NamespaceSelector is an optional field for an expression + used to select a pod based on namespaces. + type: string + order: + description: Order is an optional field that specifies the order in + which the policy is applied. Policies with higher "order" are applied + after those with lower order. If the order is omitted, it may be + considered to be "infinite" - i.e. the policy will be applied last. Policies + with identical order will be applied in alphanumerical order based + on the Policy "Name". + type: number + preDNAT: + description: PreDNAT indicates to apply the rules in this policy before + any DNAT. + type: boolean + selector: + description: "The selector is an expression used to pick pick out + the endpoints that the policy should be applied to. \n Selector + expressions follow this syntax: \n \tlabel == \"string_literal\" + \ -> comparison, e.g. my_label == \"foo bar\" \tlabel != \"string_literal\" + \ -> not equal; also matches if label is not present \tlabel in + { \"a\", \"b\", \"c\", ... } -> true if the value of label X is + one of \"a\", \"b\", \"c\" \tlabel not in { \"a\", \"b\", \"c\", + ... } -> true if the value of label X is not one of \"a\", \"b\", + \"c\" \thas(label_name) -> True if that label is present \t! expr + -> negation of expr \texpr && expr -> Short-circuit and \texpr + || expr -> Short-circuit or \t( expr ) -> parens for grouping \tall() + or the empty selector -> matches all endpoints. \n Label names are + allowed to contain alphanumerics, -, _ and /. String literals are + more permissive but they do not support escape characters. \n Examples + (with made-up labels): \n \ttype == \"webserver\" && deployment + == \"prod\" \ttype in {\"frontend\", \"backend\"} \tdeployment != + \"dev\" \t! has(label_name)" + type: string + serviceAccountSelector: + description: ServiceAccountSelector is an optional field for an expression + used to select a pod based on service accounts. + type: string + types: + description: "Types indicates whether this policy applies to ingress, + or to egress, or to both. When not explicitly specified (and so + the value on creation is empty or nil), Calico defaults Types according + to what Ingress and Egress rules are present in the policy. The + default is: \n - [ PolicyTypeIngress ], if there are no Egress rules + (including the case where there are also no Ingress rules) \n + - [ PolicyTypeEgress ], if there are Egress rules but no Ingress + rules \n - [ PolicyTypeIngress, PolicyTypeEgress ], if there are + both Ingress and Egress rules. \n When the policy is read back again, + Types will always be one of these values, never empty or nil." + items: + description: PolicyType enumerates the possible values of the PolicySpec + Types field. + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_globalnetworksets.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: globalnetworksets.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: GlobalNetworkSet + listKind: GlobalNetworkSetList + plural: globalnetworksets + singular: globalnetworkset + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: GlobalNetworkSet contains a set of arbitrary IP sub-networks/CIDRs + that share labels to allow rules to refer to them via selectors. The labels + of GlobalNetworkSet are not namespaced. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: GlobalNetworkSetSpec contains the specification for a NetworkSet + resource. + properties: + nets: + description: The list of IP networks that belong to this set. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_hostendpoints.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: hostendpoints.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: HostEndpoint + listKind: HostEndpointList + plural: hostendpoints + singular: hostendpoint + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: HostEndpointSpec contains the specification for a HostEndpoint + resource. + properties: + expectedIPs: + description: "The expected IP addresses (IPv4 and IPv6) of the endpoint. + If \"InterfaceName\" is not present, Calico will look for an interface + matching any of the IPs in the list and apply policy to that. Note: + \tWhen using the selector match criteria in an ingress or egress + security Policy \tor Profile, Calico converts the selector into + a set of IP addresses. For host \tendpoints, the ExpectedIPs field + is used for that purpose. (If only the interface \tname is specified, + Calico does not learn the IPs of the interface for use in match + \tcriteria.)" + items: + type: string + type: array + interfaceName: + description: "Either \"*\", or the name of a specific Linux interface + to apply policy to; or empty. \"*\" indicates that this HostEndpoint + governs all traffic to, from or through the default network namespace + of the host named by the \"Node\" field; entering and leaving that + namespace via any interface, including those from/to non-host-networked + local workloads. \n If InterfaceName is not \"*\", this HostEndpoint + only governs traffic that enters or leaves the host through the + specific interface named by InterfaceName, or - when InterfaceName + is empty - through the specific interface that has one of the IPs + in ExpectedIPs. Therefore, when InterfaceName is empty, at least + one expected IP must be specified. Only external interfaces (such + as \"eth0\") are supported here; it isn't possible for a HostEndpoint + to protect traffic through a specific local workload interface. + \n Note: Only some kinds of policy are implemented for \"*\" HostEndpoints; + initially just pre-DNAT policy. Please check Calico documentation + for the latest position." + type: string + node: + description: The node name identifying the Calico node instance. + type: string + ports: + description: Ports contains the endpoint's named ports, which may + be referenced in security policy rules. + items: + properties: + name: + type: string + port: + type: integer + protocol: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + required: + - name + - port + - protocol + type: object + type: array + profiles: + description: A list of identifiers of security Profile objects that + apply to this endpoint. Each profile is applied in the order that + they appear in this list. Profile rules are applied after the selector-based + security policy. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_ipamblocks.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ipamblocks.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMBlock + listKind: IPAMBlockList + plural: ipamblocks + singular: ipamblock + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPAMBlockSpec contains the specification for an IPAMBlock + resource. + properties: + affinity: + description: Affinity of the block, if this block has one. If set, + it will be of the form "host:". If not set, this block + is not affine to a host. + type: string + allocations: + description: Array of allocations in-use within this block. nil entries + mean the allocation is free. For non-nil entries at index i, the + index is the ordinal of the allocation within this block and the + value is the index of the associated attributes in the Attributes + array. + items: + type: integer + # TODO: This nullable is manually added in. We should update controller-gen + # to handle []*int properly itself. + nullable: true + type: array + attributes: + description: Attributes is an array of arbitrary metadata associated + with allocations in the block. To find attributes for a given allocation, + use the value of the allocation's entry in the Allocations array + as the index of the element in this array. + items: + properties: + handle_id: + type: string + secondary: + additionalProperties: + type: string + type: object + type: object + type: array + cidr: + description: The block's CIDR. + type: string + deleted: + description: Deleted is an internal boolean used to workaround a limitation + in the Kubernetes API whereby deletion will not return a conflict + error if the block has been updated. It should not be set manually. + type: boolean + sequenceNumber: + default: 0 + description: We store a sequence number that is updated each time + the block is written. Each allocation will also store the sequence + number of the block at the time of its creation. When releasing + an IP, passing the sequence number associated with the allocation + allows us to protect against a race condition and ensure the IP + hasn't been released and re-allocated since the release request. + format: int64 + type: integer + sequenceNumberForAllocation: + additionalProperties: + format: int64 + type: integer + description: Map of allocated ordinal within the block to sequence + number of the block at the time of allocation. Kubernetes does not + allow numerical keys for maps, so the key is cast to a string. + type: object + strictAffinity: + description: StrictAffinity on the IPAMBlock is deprecated and no + longer used by the code. Use IPAMConfig StrictAffinity instead. + type: boolean + unallocated: + description: Unallocated is an ordered list of allocations which are + free in the block. + items: + type: integer + type: array + required: + - allocations + - attributes + - cidr + - strictAffinity + - unallocated + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_ipamconfigs.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ipamconfigs.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMConfig + listKind: IPAMConfigList + plural: ipamconfigs + singular: ipamconfig + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPAMConfigSpec contains the specification for an IPAMConfig + resource. + properties: + autoAllocateBlocks: + type: boolean + maxBlocksPerHost: + description: MaxBlocksPerHost, if non-zero, is the max number of blocks + that can be affine to each host. + maximum: 2147483647 + minimum: 0 + type: integer + strictAffinity: + type: boolean + required: + - autoAllocateBlocks + - strictAffinity + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_ipamhandles.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ipamhandles.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPAMHandle + listKind: IPAMHandleList + plural: ipamhandles + singular: ipamhandle + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPAMHandleSpec contains the specification for an IPAMHandle + resource. + properties: + block: + additionalProperties: + type: integer + type: object + deleted: + type: boolean + handleID: + type: string + required: + - block + - handleID + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_ippools.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: ippools.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPPool + listKind: IPPoolList + plural: ippools + singular: ippool + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPPoolSpec contains the specification for an IPPool resource. + properties: + allowedUses: + description: AllowedUse controls what the IP pool will be used for. If + not specified or empty, defaults to ["Tunnel", "Workload"] for back-compatibility + items: + type: string + type: array + blockSize: + description: The block size to use for IP address assignments from + this pool. Defaults to 26 for IPv4 and 122 for IPv6. + type: integer + cidr: + description: The pool CIDR. + type: string + disableBGPExport: + description: 'Disable exporting routes from this IP Pool''s CIDR over + BGP. [Default: false]' + type: boolean + disabled: + description: When disabled is true, Calico IPAM will not assign addresses + from this pool. + type: boolean + ipip: + description: 'Deprecated: this field is only used for APIv1 backwards + compatibility. Setting this field is not allowed, this field is + for internal use only.' + properties: + enabled: + description: When enabled is true, ipip tunneling will be used + to deliver packets to destinations within this pool. + type: boolean + mode: + description: The IPIP mode. This can be one of "always" or "cross-subnet". A + mode of "always" will also use IPIP tunneling for routing to + destination IP addresses within this pool. A mode of "cross-subnet" + will only use IPIP tunneling when the destination node is on + a different subnet to the originating node. The default value + (if not specified) is "always". + type: string + type: object + ipipMode: + description: Contains configuration for IPIP tunneling for this pool. + If not specified, then this is defaulted to "Never" (i.e. IPIP tunneling + is disabled). + type: string + nat-outgoing: + description: 'Deprecated: this field is only used for APIv1 backwards + compatibility. Setting this field is not allowed, this field is + for internal use only.' + type: boolean + natOutgoing: + description: When nat-outgoing is true, packets sent from Calico networked + containers in this pool to destinations outside of this pool will + be masqueraded. + type: boolean + nodeSelector: + description: Allows IPPool to allocate for a specific node by label + selector. + type: string + vxlanMode: + description: Contains configuration for VXLAN tunneling for this pool. + If not specified, then this is defaulted to "Never" (i.e. VXLAN + tunneling is disabled). + type: string + required: + - cidr + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_ipreservations.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: (devel) + creationTimestamp: null + name: ipreservations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: IPReservation + listKind: IPReservationList + plural: ipreservations + singular: ipreservation + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IPReservationSpec contains the specification for an IPReservation + resource. + properties: + reservedCIDRs: + description: ReservedCIDRs is a list of CIDRs and/or IP addresses + that Calico IPAM will exclude from new allocations. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_kubecontrollersconfigurations.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: kubecontrollersconfigurations.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: KubeControllersConfiguration + listKind: KubeControllersConfigurationList + plural: kubecontrollersconfigurations + singular: kubecontrollersconfiguration + preserveUnknownFields: false + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: KubeControllersConfigurationSpec contains the values of the + Kubernetes controllers configuration. + properties: + controllers: + description: Controllers enables and configures individual Kubernetes + controllers + properties: + namespace: + description: Namespace enables and configures the namespace controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + node: + description: Node enables and configures the node controller. + Enabled by default, set to nil to disable. + properties: + hostEndpoint: + description: HostEndpoint controls syncing nodes to host endpoints. + Disabled by default, set to nil to disable. + properties: + autoCreate: + description: 'AutoCreate enables automatic creation of + host endpoints for every node. [Default: Disabled]' + type: string + type: object + leakGracePeriod: + description: 'LeakGracePeriod is the period used by the controller + to determine if an IP address has been leaked. Set to 0 + to disable IP garbage collection. [Default: 15m]' + type: string + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + syncLabels: + description: 'SyncLabels controls whether to copy Kubernetes + node labels to Calico nodes. [Default: Enabled]' + type: string + type: object + policy: + description: Policy enables and configures the policy controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + serviceAccount: + description: ServiceAccount enables and configures the service + account controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + workloadEndpoint: + description: WorkloadEndpoint enables and configures the workload + endpoint controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform reconciliation + with the Calico datastore. [Default: 5m]' + type: string + type: object + type: object + debugProfilePort: + description: DebugProfilePort configures the port to serve memory + and cpu profiles on. If not specified, profiling is disabled. + format: int32 + type: integer + etcdV3CompactionPeriod: + description: 'EtcdV3CompactionPeriod is the period between etcdv3 + compaction requests. Set to 0 to disable. [Default: 10m]' + type: string + healthChecks: + description: 'HealthChecks enables or disables support for health + checks [Default: Enabled]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which logs + are sent to the stdout. [Default: Info]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. Set to 0 to disable. [Default: 9094]' + type: integer + required: + - controllers + type: object + status: + description: KubeControllersConfigurationStatus represents the status + of the configuration. It's useful for admins to be able to see the actual + config that was applied, which can be modified by environment variables + on the kube-controllers process. + properties: + environmentVars: + additionalProperties: + type: string + description: EnvironmentVars contains the environment variables on + the kube-controllers that influenced the RunningConfig. + type: object + runningConfig: + description: RunningConfig contains the effective config that is running + in the kube-controllers pod, after merging the API resource with + any environment variables. + properties: + controllers: + description: Controllers enables and configures individual Kubernetes + controllers + properties: + namespace: + description: Namespace enables and configures the namespace + controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + node: + description: Node enables and configures the node controller. + Enabled by default, set to nil to disable. + properties: + hostEndpoint: + description: HostEndpoint controls syncing nodes to host + endpoints. Disabled by default, set to nil to disable. + properties: + autoCreate: + description: 'AutoCreate enables automatic creation + of host endpoints for every node. [Default: Disabled]' + type: string + type: object + leakGracePeriod: + description: 'LeakGracePeriod is the period used by the + controller to determine if an IP address has been leaked. + Set to 0 to disable IP garbage collection. [Default: + 15m]' + type: string + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + syncLabels: + description: 'SyncLabels controls whether to copy Kubernetes + node labels to Calico nodes. [Default: Enabled]' + type: string + type: object + policy: + description: Policy enables and configures the policy controller. + Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + serviceAccount: + description: ServiceAccount enables and configures the service + account controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + workloadEndpoint: + description: WorkloadEndpoint enables and configures the workload + endpoint controller. Enabled by default, set to nil to disable. + properties: + reconcilerPeriod: + description: 'ReconcilerPeriod is the period to perform + reconciliation with the Calico datastore. [Default: + 5m]' + type: string + type: object + type: object + debugProfilePort: + description: DebugProfilePort configures the port to serve memory + and cpu profiles on. If not specified, profiling is disabled. + format: int32 + type: integer + etcdV3CompactionPeriod: + description: 'EtcdV3CompactionPeriod is the period between etcdv3 + compaction requests. Set to 0 to disable. [Default: 10m]' + type: string + healthChecks: + description: 'HealthChecks enables or disables support for health + checks [Default: Enabled]' + type: string + logSeverityScreen: + description: 'LogSeverityScreen is the log severity above which + logs are sent to the stdout. [Default: Info]' + type: string + prometheusMetricsPort: + description: 'PrometheusMetricsPort is the TCP port that the Prometheus + metrics server should bind to. Set to 0 to disable. [Default: + 9094]' + type: integer + required: + - controllers + type: object + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_networkpolicies.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networkpolicies.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: NetworkPolicy + listKind: NetworkPolicyList + plural: networkpolicies + singular: networkpolicy + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + properties: + egress: + description: The ordered set of egress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + ingress: + description: The ordered set of ingress rules. Each rule contains + a set of packet match criteria and a corresponding action to apply. + items: + description: "A Rule encapsulates a set of match criteria and an + action. Both selector-based security Policy and security Profiles + reference rules - separated out as a list of rules for both ingress + and egress packet matching. \n Each positive match criteria has + a negated version, prefixed with \"Not\". All the match criteria + within a rule must be satisfied for a packet to match. A single + rule can contain the positive and negative version of a match + and both must be satisfied for the rule to match." + properties: + action: + type: string + destination: + description: Destination contains the match criteria that apply + to destination entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + http: + description: HTTP contains match criteria that apply to HTTP + requests. + properties: + methods: + description: Methods is an optional field that restricts + the rule to apply only to HTTP requests that use one of + the listed HTTP Methods (e.g. GET, PUT, etc.) Multiple + methods are OR'd together. + items: + type: string + type: array + paths: + description: 'Paths is an optional field that restricts + the rule to apply to HTTP requests that use one of the + listed HTTP Paths. Multiple paths are OR''d together. + e.g: - exact: /foo - prefix: /bar NOTE: Each entry may + ONLY specify either a `exact` or a `prefix` match. The + validator will check for it.' + items: + description: 'HTTPPath specifies an HTTP path to match. + It may be either of the form: exact: : which matches + the path exactly or prefix: : which matches + the path prefix' + properties: + exact: + type: string + prefix: + type: string + type: object + type: array + type: object + icmp: + description: ICMP is an optional field that restricts the rule + to apply to a specific type and code of ICMP traffic. This + should only be specified if the Protocol field is set to "ICMP" + or "ICMPv6". + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + ipVersion: + description: IPVersion is an optional field that restricts the + rule to only match a specific IP version. + type: integer + metadata: + description: Metadata contains additional information for this + rule + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a set of key value pairs that + give extra information about the rule + type: object + type: object + notICMP: + description: NotICMP is the negated version of the ICMP field. + properties: + code: + description: Match on a specific ICMP code. If specified, + the Type value must also be specified. This is a technical + limitation imposed by the kernel's iptables firewall, + which Calico uses to enforce the rule. + type: integer + type: + description: Match on a specific ICMP type. For example + a value of 8 refers to ICMP Echo Request (i.e. pings). + type: integer + type: object + notProtocol: + anyOf: + - type: integer + - type: string + description: NotProtocol is the negated version of the Protocol + field. + pattern: ^.* + x-kubernetes-int-or-string: true + protocol: + anyOf: + - type: integer + - type: string + description: "Protocol is an optional field that restricts the + rule to only apply to traffic of a specific IP protocol. Required + if any of the EntityRules contain Ports (because ports only + apply to certain protocols). \n Must be one of these string + values: \"TCP\", \"UDP\", \"ICMP\", \"ICMPv6\", \"SCTP\", + \"UDPLite\" or an integer in the range 1-255." + pattern: ^.* + x-kubernetes-int-or-string: true + source: + description: Source contains the match criteria that apply to + source entity. + properties: + namespaceSelector: + description: "NamespaceSelector is an optional field that + contains a selector expression. Only traffic that originates + from (or terminates at) endpoints within the selected + namespaces will be matched. When both NamespaceSelector + and another selector are defined on the same rule, then + only workload endpoints that are matched by both selectors + will be selected by the rule. \n For NetworkPolicy, an + empty NamespaceSelector implies that the Selector is limited + to selecting only workload endpoints in the same namespace + as the NetworkPolicy. \n For NetworkPolicy, `global()` + NamespaceSelector implies that the Selector is limited + to selecting only GlobalNetworkSet or HostEndpoint. \n + For GlobalNetworkPolicy, an empty NamespaceSelector implies + the Selector applies to workload endpoints across all + namespaces." + type: string + nets: + description: Nets is an optional field that restricts the + rule to only apply to traffic that originates from (or + terminates at) IP addresses in any of the given subnets. + items: + type: string + type: array + notNets: + description: NotNets is the negated version of the Nets + field. + items: + type: string + type: array + notPorts: + description: NotPorts is the negated version of the Ports + field. Since only some protocols have ports, if any ports + are specified it requires the Protocol match in the Rule + to be set to "TCP" or "UDP". + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + notSelector: + description: NotSelector is the negated version of the Selector + field. See Selector field for subtleties with negated + selectors. + type: string + ports: + description: "Ports is an optional field that restricts + the rule to only apply to traffic that has a source (destination) + port that matches one of these ranges/values. This value + is a list of integers or strings that represent ranges + of ports. \n Since only some protocols have ports, if + any ports are specified it requires the Protocol match + in the Rule to be set to \"TCP\" or \"UDP\"." + items: + anyOf: + - type: integer + - type: string + pattern: ^.* + x-kubernetes-int-or-string: true + type: array + selector: + description: "Selector is an optional field that contains + a selector expression (see Policy for sample syntax). + \ Only traffic that originates from (terminates at) endpoints + matching the selector will be matched. \n Note that: in + addition to the negated version of the Selector (see NotSelector + below), the selector expression syntax itself supports + negation. The two types of negation are subtly different. + One negates the set of matched endpoints, the other negates + the whole match: \n \tSelector = \"!has(my_label)\" matches + packets that are from other Calico-controlled \tendpoints + that do not have the label \"my_label\". \n \tNotSelector + = \"has(my_label)\" matches packets that are not from + Calico-controlled \tendpoints that do have the label \"my_label\". + \n The effect is that the latter will accept packets from + non-Calico sources whereas the former is limited to packets + from Calico-controlled endpoints." + type: string + serviceAccounts: + description: ServiceAccounts is an optional field that restricts + the rule to only apply to traffic that originates from + (or terminates at) a pod running as a matching service + account. + properties: + names: + description: Names is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account whose name is in the list. + items: + type: string + type: array + selector: + description: Selector is an optional field that restricts + the rule to only apply to traffic that originates + from (or terminates at) a pod running as a service + account that matches the given label selector. If + both Names and Selector are specified then they are + AND'ed. + type: string + type: object + services: + description: "Services is an optional field that contains + options for matching Kubernetes Services. If specified, + only traffic that originates from or terminates at endpoints + within the selected service(s) will be matched, and only + to/from each endpoint's port. \n Services cannot be specified + on the same rule as Selector, NotSelector, NamespaceSelector, + Nets, NotNets or ServiceAccounts. \n Ports and NotPorts + can only be specified with Services on ingress rules." + properties: + name: + description: Name specifies the name of a Kubernetes + Service to match. + type: string + namespace: + description: Namespace specifies the namespace of the + given Service. If left empty, the rule will match + within this policy's namespace. + type: string + type: object + type: object + required: + - action + type: object + type: array + order: + description: Order is an optional field that specifies the order in + which the policy is applied. Policies with higher "order" are applied + after those with lower order. If the order is omitted, it may be + considered to be "infinite" - i.e. the policy will be applied last. Policies + with identical order will be applied in alphanumerical order based + on the Policy "Name". + type: number + selector: + description: "The selector is an expression used to pick pick out + the endpoints that the policy should be applied to. \n Selector + expressions follow this syntax: \n \tlabel == \"string_literal\" + \ -> comparison, e.g. my_label == \"foo bar\" \tlabel != \"string_literal\" + \ -> not equal; also matches if label is not present \tlabel in + { \"a\", \"b\", \"c\", ... } -> true if the value of label X is + one of \"a\", \"b\", \"c\" \tlabel not in { \"a\", \"b\", \"c\", + ... } -> true if the value of label X is not one of \"a\", \"b\", + \"c\" \thas(label_name) -> True if that label is present \t! expr + -> negation of expr \texpr && expr -> Short-circuit and \texpr + || expr -> Short-circuit or \t( expr ) -> parens for grouping \tall() + or the empty selector -> matches all endpoints. \n Label names are + allowed to contain alphanumerics, -, _ and /. String literals are + more permissive but they do not support escape characters. \n Examples + (with made-up labels): \n \ttype == \"webserver\" && deployment + == \"prod\" \ttype in {\"frontend\", \"backend\"} \tdeployment != + \"dev\" \t! has(label_name)" + type: string + serviceAccountSelector: + description: ServiceAccountSelector is an optional field for an expression + used to select a pod based on service accounts. + type: string + types: + description: "Types indicates whether this policy applies to ingress, + or to egress, or to both. When not explicitly specified (and so + the value on creation is empty or nil), Calico defaults Types according + to what Ingress and Egress are present in the policy. The default + is: \n - [ PolicyTypeIngress ], if there are no Egress rules (including + the case where there are also no Ingress rules) \n - [ PolicyTypeEgress + ], if there are Egress rules but no Ingress rules \n - [ PolicyTypeIngress, + PolicyTypeEgress ], if there are both Ingress and Egress rules. + \n When the policy is read back again, Types will always be one + of these values, never empty or nil." + items: + description: PolicyType enumerates the possible values of the PolicySpec + Types field. + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/calico/crd.projectcalico.org_networksets.yaml +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: networksets.crd.projectcalico.org +spec: + group: crd.projectcalico.org + names: + kind: NetworkSet + listKind: NetworkSetList + plural: networksets + singular: networkset + preserveUnknownFields: false + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: NetworkSet is the Namespaced-equivalent of the GlobalNetworkSet. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: NetworkSetSpec contains the specification for a NetworkSet + resource. + properties: + nets: + description: The list of IP networks that belong to this set. + items: + type: string + type: array + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/operator.tigera.io_apiservers_crd.yaml + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + name: apiservers.operator.tigera.io +spec: + group: operator.tigera.io + names: + kind: APIServer + listKind: APIServerList + plural: apiservers + singular: apiserver + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: APIServer installs the Tigera API server and related resources. + At most one instance of this resource is supported. It must be named "tigera-secure". + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Specification of the desired state for the Tigera API server. + properties: + apiServerDeployment: + description: APIServerDeployment configures the calico-apiserver (or + tigera-apiserver in Enterprise) Deployment. If used in conjunction + with ControlPlaneNodeSelector or ControlPlaneTolerations, then these + overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's metadata + that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to the + object's annotations provided the key does not already exist + in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values that + may match replicaset and service selectors. Each of these + key/value pairs are added to the object's labels provided + the key does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the specification of the API server Deployment. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of seconds + for which a newly created Deployment pod should be ready + without any of its container crashing, for it to be considered + available. If specified, this overrides any minReadySeconds + value that may be set on the API server Deployment. If omitted, + the API server Deployment will use its default value for + minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the API server Deployment + pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added + to the object's annotations provided the key does + not already exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. + Each of these key/value pairs are added to the object's + labels provided the key does not already exist in + the object's labels. + type: object + type: object + spec: + description: Spec is the API server Deployment's PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity scheduling + rules for the API server pods. If specified, this + overrides any affinity that may be set on the API + server Deployment. If omitted, the API server Deployment + will use its default value for affinity. WARNING: + Please note that this field will override the default + API server Deployment affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of API server containers. + If specified, this overrides the specified API server + Deployment containers. If omitted, the API server + Deployment will use its default values for its containers. + items: + description: APIServerDeploymentContainer is an + API server Deployment container. + properties: + name: + description: Name is an enum which identifies + the API server Deployment container by name. + enum: + - calico-apiserver + - tigera-queryserver + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named API server Deployment + container's resources. If omitted, the API + server Deployment will use its default value + for this container's resources. If used in + conjunction with the deprecated ComponentResources, + then this value takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + initContainers: + description: InitContainers is a list of API server + init containers. If specified, this overrides the + specified API server Deployment init containers. + If omitted, the API server Deployment will use its + default values for its init containers. + items: + description: APIServerDeploymentInitContainer is + an API server Deployment init container. + properties: + name: + description: Name is an enum which identifies + the API server Deployment init container by + name. + enum: + - calico-apiserver-certs-key-cert-provisioner + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named API server Deployment + init container's resources. If omitted, the + API server Deployment will use its default + value for this init container's resources. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the API server pod''s + scheduling constraints. If specified, each of the + key/value pairs are added to the API server Deployment + nodeSelector provided the key does not already exist + in the object''s nodeSelector. If used in conjunction + with ControlPlaneNodeSelector, that nodeSelector + is set on the API server Deployment and each of + this field''s key/value pairs are added to the API + server Deployment nodeSelector provided the key + does not already exist in the object''s nodeSelector. + If omitted, the API server Deployment will use its + default value for nodeSelector. WARNING: Please + note that this field will modify the default API + server Deployment nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the API server pod''s + tolerations. If specified, this overrides any tolerations + that may be set on the API server Deployment. If + omitted, the API server Deployment will use its + default value for tolerations. WARNING: Please note + that this field will override the default API server + Deployment tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + type: object + status: + description: Most recently observed status for the Tigera API server. + properties: + state: + description: State provides user-readable status. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/operator.tigera.io_imagesets_crd.yaml + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + name: imagesets.operator.tigera.io +spec: + group: operator.tigera.io + names: + kind: ImageSet + listKind: ImageSetList + plural: imagesets + singular: imageset + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: ImageSet is used to specify image digests for the images that + the operator deploys. The name of the ImageSet is expected to be in the + format `-`. The `variant` used is `enterprise` if the + InstallationSpec Variant is `TigeraSecureEnterprise` otherwise it is `calico`. + The `release` must match the version of the variant that the operator is + built to deploy, this version can be obtained by passing the `--version` + flag to the operator binary. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ImageSetSpec defines the desired state of ImageSet. + properties: + images: + description: Images is the list of images to use digests. All images + that the operator will deploy must be specified. + items: + properties: + digest: + description: Digest is the image identifier that will be used + for the Image. The field should not include a leading `@` + and must be prefixed with `sha256:`. + type: string + image: + description: Image is an image that the operator deploys and + instead of using the built in tag the operator will use the + Digest for the image identifier. The value should be the image + name without registry or tag or digest. For the image `docker.io/calico/node:v3.17.1` + it should be represented as `calico/node` + type: string + required: + - digest + - image + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/operator.tigera.io_installations_crd.yaml + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + name: installations.operator.tigera.io +spec: + group: operator.tigera.io + names: + kind: Installation + listKind: InstallationList + plural: installations + singular: installation + scope: Cluster + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Installation configures an installation of Calico or Calico Enterprise. + At most one instance of this resource is supported. It must be named "default". + The Installation API installs core networking and network policy components, + and provides general install-time configuration. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Specification of the desired state for the Calico or Calico + Enterprise installation. + properties: + calicoKubeControllersDeployment: + description: CalicoKubeControllersDeployment configures the calico-kube-controllers + Deployment. If used in conjunction with the deprecated ComponentResources, + then these overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's metadata + that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to the + object's annotations provided the key does not already exist + in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values that + may match replicaset and service selectors. Each of these + key/value pairs are added to the object's labels provided + the key does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the specification of the calico-kube-controllers + Deployment. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of seconds + for which a newly created Deployment pod should be ready + without any of its container crashing, for it to be considered + available. If specified, this overrides any minReadySeconds + value that may be set on the calico-kube-controllers Deployment. + If omitted, the calico-kube-controllers Deployment will + use its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the calico-kube-controllers + Deployment pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added + to the object's annotations provided the key does + not already exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. + Each of these key/value pairs are added to the object's + labels provided the key does not already exist in + the object's labels. + type: object + type: object + spec: + description: Spec is the calico-kube-controllers Deployment's + PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity scheduling + rules for the calico-kube-controllers pods. If specified, + this overrides any affinity that may be set on the + calico-kube-controllers Deployment. If omitted, + the calico-kube-controllers Deployment will use + its default value for affinity. WARNING: Please + note that this field will override the default calico-kube-controllers + Deployment affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of calico-kube-controllers + containers. If specified, this overrides the specified + calico-kube-controllers Deployment containers. If + omitted, the calico-kube-controllers Deployment + will use its default values for its containers. + items: + description: CalicoKubeControllersDeploymentContainer + is a calico-kube-controllers Deployment container. + properties: + name: + description: Name is an enum which identifies + the calico-kube-controllers Deployment container + by name. + enum: + - calico-kube-controllers + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named calico-kube-controllers + Deployment container's resources. If omitted, + the calico-kube-controllers Deployment will + use its default value for this container's + resources. If used in conjunction with the + deprecated ComponentResources, then this value + takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-kube-controllers + pod''s scheduling constraints. If specified, each + of the key/value pairs are added to the calico-kube-controllers + Deployment nodeSelector provided the key does not + already exist in the object''s nodeSelector. If + used in conjunction with ControlPlaneNodeSelector, + that nodeSelector is set on the calico-kube-controllers + Deployment and each of this field''s key/value pairs + are added to the calico-kube-controllers Deployment + nodeSelector provided the key does not already exist + in the object''s nodeSelector. If omitted, the calico-kube-controllers + Deployment will use its default value for nodeSelector. + WARNING: Please note that this field will modify + the default calico-kube-controllers Deployment nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the calico-kube-controllers + pod''s tolerations. If specified, this overrides + any tolerations that may be set on the calico-kube-controllers + Deployment. If omitted, the calico-kube-controllers + Deployment will use its default value for tolerations. + WARNING: Please note that this field will override + the default calico-kube-controllers Deployment tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + calicoNetwork: + description: CalicoNetwork specifies networking configuration options + for Calico. + properties: + bgp: + description: BGP configures whether or not to enable Calico's + BGP capabilities. + enum: + - Enabled + - Disabled + type: string + containerIPForwarding: + description: 'ContainerIPForwarding configures whether ip forwarding + will be enabled for containers in the CNI configuration. Default: + Disabled' + enum: + - Enabled + - Disabled + type: string + hostPorts: + description: 'HostPorts configures whether or not Calico will + support Kubernetes HostPorts. Valid only when using the Calico + CNI plugin. Default: Enabled' + enum: + - Enabled + - Disabled + type: string + ipPools: + description: IPPools contains a list of IP pools to create if + none exist. At most one IP pool of each address family may be + specified. If omitted, a single pool will be configured if needed. + items: + properties: + blockSize: + description: 'BlockSize specifies the CIDR prefex length + to use when allocating per-node IP blocks from the main + IP pool CIDR. Default: 26 (IPv4), 122 (IPv6)' + format: int32 + type: integer + cidr: + description: CIDR contains the address range for the IP + Pool in classless inter-domain routing format. + type: string + disableBGPExport: + default: false + description: 'DisableBGPExport specifies whether routes + from this IP pool''s CIDR are exported over BGP. Default: + false' + type: boolean + encapsulation: + description: 'Encapsulation specifies the encapsulation + type that will be used with the IP Pool. Default: IPIP' + enum: + - IPIPCrossSubnet + - IPIP + - VXLAN + - VXLANCrossSubnet + - None + type: string + natOutgoing: + description: 'NATOutgoing specifies if NAT will be enabled + or disabled for outgoing traffic. Default: Enabled' + enum: + - Enabled + - Disabled + type: string + nodeSelector: + description: 'NodeSelector specifies the node selector that + will be set for the IP Pool. Default: ''all()''' + type: string + required: + - cidr + type: object + type: array + linuxDataplane: + description: 'LinuxDataplane is used to select the dataplane used + for Linux nodes. In particular, it causes the operator to add + required mounts and environment variables for the particular + dataplane. If not specified, iptables mode is used. Default: + Iptables' + enum: + - Iptables + - BPF + - VPP + type: string + mtu: + description: MTU specifies the maximum transmission unit to use + on the pod network. If not specified, Calico will perform MTU + auto-detection based on the cluster network. + format: int32 + type: integer + multiInterfaceMode: + description: 'MultiInterfaceMode configures what will configure + multiple interface per pod. Only valid for Calico Enterprise + installations using the Calico CNI plugin. Default: None' + enum: + - None + - Multus + type: string + nodeAddressAutodetectionV4: + description: NodeAddressAutodetectionV4 specifies an approach + to automatically detect node IPv4 addresses. If not specified, + will use default auto-detection settings to acquire an IPv4 + address for each node. + properties: + canReach: + description: CanReach enables IP auto-detection based on which + source address on the node is used to reach the specified + IP or domain. + type: string + cidrs: + description: CIDRS enables IP auto-detection based on which + addresses on the nodes are within one of the provided CIDRs. + items: + type: string + type: array + firstFound: + description: FirstFound uses default interface matching parameters + to select an interface, performing best-effort filtering + based on well-known interface names. + type: boolean + interface: + description: Interface enables IP auto-detection based on + interfaces that match the given regex. + type: string + kubernetes: + description: Kubernetes configures Calico to detect node addresses + based on the Kubernetes API. + enum: + - NodeInternalIP + type: string + skipInterface: + description: SkipInterface enables IP auto-detection based + on interfaces that do not match the given regex. + type: string + type: object + nodeAddressAutodetectionV6: + description: NodeAddressAutodetectionV6 specifies an approach + to automatically detect node IPv6 addresses. If not specified, + IPv6 addresses will not be auto-detected. + properties: + canReach: + description: CanReach enables IP auto-detection based on which + source address on the node is used to reach the specified + IP or domain. + type: string + cidrs: + description: CIDRS enables IP auto-detection based on which + addresses on the nodes are within one of the provided CIDRs. + items: + type: string + type: array + firstFound: + description: FirstFound uses default interface matching parameters + to select an interface, performing best-effort filtering + based on well-known interface names. + type: boolean + interface: + description: Interface enables IP auto-detection based on + interfaces that match the given regex. + type: string + kubernetes: + description: Kubernetes configures Calico to detect node addresses + based on the Kubernetes API. + enum: + - NodeInternalIP + type: string + skipInterface: + description: SkipInterface enables IP auto-detection based + on interfaces that do not match the given regex. + type: string + type: object + type: object + calicoNodeDaemonSet: + description: CalicoNodeDaemonSet configures the calico-node DaemonSet. + If used in conjunction with the deprecated ComponentResources, then + these overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's metadata + that is added to the DaemonSet. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to the + object's annotations provided the key does not already exist + in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values that + may match replicaset and service selectors. Each of these + key/value pairs are added to the object's labels provided + the key does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the specification of the calico-node DaemonSet. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of seconds + for which a newly created DaemonSet pod should be ready + without any of its container crashing, for it to be considered + available. If specified, this overrides any minReadySeconds + value that may be set on the calico-node DaemonSet. If omitted, + the calico-node DaemonSet will use its default value for + minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the calico-node DaemonSet + pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added + to the object's annotations provided the key does + not already exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. + Each of these key/value pairs are added to the object's + labels provided the key does not already exist in + the object's labels. + type: object + type: object + spec: + description: Spec is the calico-node DaemonSet's PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity scheduling + rules for the calico-node pods. If specified, this + overrides any affinity that may be set on the calico-node + DaemonSet. If omitted, the calico-node DaemonSet + will use its default value for affinity. WARNING: + Please note that this field will override the default + calico-node DaemonSet affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of calico-node containers. + If specified, this overrides the specified calico-node + DaemonSet containers. If omitted, the calico-node + DaemonSet will use its default values for its containers. + items: + description: CalicoNodeDaemonSetContainer is a calico-node + DaemonSet container. + properties: + name: + description: Name is an enum which identifies + the calico-node DaemonSet container by name. + enum: + - calico-node + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named calico-node DaemonSet + container's resources. If omitted, the calico-node + DaemonSet will use its default value for this + container's resources. If used in conjunction + with the deprecated ComponentResources, then + this value takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + initContainers: + description: InitContainers is a list of calico-node + init containers. If specified, this overrides the + specified calico-node DaemonSet init containers. + If omitted, the calico-node DaemonSet will use its + default values for its init containers. + items: + description: CalicoNodeDaemonSetInitContainer is + a calico-node DaemonSet init container. + properties: + name: + description: Name is an enum which identifies + the calico-node DaemonSet init container by + name. + enum: + - install-cni + - hostpath-init + - flexvol-driver + - mount-bpffs + - node-certs-key-cert-provisioner + - calico-node-prometheus-server-tls-key-cert-provisioner + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named calico-node DaemonSet + init container's resources. If omitted, the + calico-node DaemonSet will use its default + value for this container's resources. If used + in conjunction with the deprecated ComponentResources, + then this value takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-node pod''s + scheduling constraints. If specified, each of the + key/value pairs are added to the calico-node DaemonSet + nodeSelector provided the key does not already exist + in the object''s nodeSelector. If omitted, the calico-node + DaemonSet will use its default value for nodeSelector. + WARNING: Please note that this field will modify + the default calico-node DaemonSet nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the calico-node pod''s + tolerations. If specified, this overrides any tolerations + that may be set on the calico-node DaemonSet. If + omitted, the calico-node DaemonSet will use its + default value for tolerations. WARNING: Please note + that this field will override the default calico-node + DaemonSet tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + calicoWindowsUpgradeDaemonSet: + description: CalicoWindowsUpgradeDaemonSet configures the calico-windows-upgrade + DaemonSet. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's metadata + that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to the + object's annotations provided the key does not already exist + in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values that + may match replicaset and service selectors. Each of these + key/value pairs are added to the object's labels provided + the key does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the specification of the calico-windows-upgrade + DaemonSet. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of seconds + for which a newly created Deployment pod should be ready + without any of its container crashing, for it to be considered + available. If specified, this overrides any minReadySeconds + value that may be set on the calico-windows-upgrade DaemonSet. + If omitted, the calico-windows-upgrade DaemonSet will use + its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the calico-windows-upgrade + DaemonSet pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added + to the object's annotations provided the key does + not already exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. + Each of these key/value pairs are added to the object's + labels provided the key does not already exist in + the object's labels. + type: object + type: object + spec: + description: Spec is the calico-windows-upgrade DaemonSet's + PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity scheduling + rules for the calico-windows-upgrade pods. If specified, + this overrides any affinity that may be set on the + calico-windows-upgrade DaemonSet. If omitted, the + calico-windows-upgrade DaemonSet will use its default + value for affinity. WARNING: Please note that this + field will override the default calico-windows-upgrade + DaemonSet affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of calico-windows-upgrade + containers. If specified, this overrides the specified + calico-windows-upgrade DaemonSet containers. If + omitted, the calico-windows-upgrade DaemonSet will + use its default values for its containers. + items: + description: CalicoWindowsUpgradeDaemonSetContainer + is a calico-windows-upgrade DaemonSet container. + properties: + name: + description: Name is an enum which identifies + the calico-windows-upgrade DaemonSet container + by name. + enum: + - calico-windows-upgrade + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named calico-windows-upgrade + DaemonSet container's resources. If omitted, + the calico-windows-upgrade DaemonSet will + use its default value for this container's + resources. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-windows-upgrade + pod''s scheduling constraints. If specified, each + of the key/value pairs are added to the calico-windows-upgrade + DaemonSet nodeSelector provided the key does not + already exist in the object''s nodeSelector. If + omitted, the calico-windows-upgrade DaemonSet will + use its default value for nodeSelector. WARNING: + Please note that this field will modify the default + calico-windows-upgrade DaemonSet nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the calico-windows-upgrade + pod''s tolerations. If specified, this overrides + any tolerations that may be set on the calico-windows-upgrade + DaemonSet. If omitted, the calico-windows-upgrade + DaemonSet will use its default value for tolerations. + WARNING: Please note that this field will override + the default calico-windows-upgrade DaemonSet tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + certificateManagement: + description: CertificateManagement configures pods to submit a CertificateSigningRequest + to the certificates.k8s.io/v1beta1 API in order to obtain TLS certificates. + This feature requires that you bring your own CSR signing and approval + process, otherwise pods will be stuck during initialization. + properties: + caCert: + description: Certificate of the authority that signs the CertificateSigningRequests + in PEM format. + format: byte + type: string + keyAlgorithm: + description: 'Specify the algorithm used by pods to generate a + key pair that is associated with the X.509 certificate request. + Default: RSAWithSize2048' + enum: + - "" + - RSAWithSize2048 + - RSAWithSize4096 + - RSAWithSize8192 + - ECDSAWithCurve256 + - ECDSAWithCurve384 + - ECDSAWithCurve521 + type: string + signatureAlgorithm: + description: 'Specify the algorithm used for the signature of + the X.509 certificate request. Default: SHA256WithRSA' + enum: + - "" + - SHA256WithRSA + - SHA384WithRSA + - SHA512WithRSA + - ECDSAWithSHA256 + - ECDSAWithSHA384 + - ECDSAWithSHA512 + type: string + signerName: + description: 'When a CSR is issued to the certificates.k8s.io + API, the signerName is added to the request in order to accommodate + for clusters with multiple signers. Must be formatted as: `/`.' + type: string + required: + - caCert + - signerName + type: object + cni: + description: CNI specifies the CNI that will be used by this installation. + properties: + ipam: + description: IPAM specifies the pod IP address management that + will be used in the Calico or Calico Enterprise installation. + properties: + type: + description: "Specifies the IPAM plugin that will be used + in the Calico or Calico Enterprise installation. * For CNI + Plugin Calico, this field defaults to Calico. * For CNI + Plugin GKE, this field defaults to HostLocal. * For CNI + Plugin AzureVNET, this field defaults to AzureVNET. * For + CNI Plugin AmazonVPC, this field defaults to AmazonVPC. + \n The IPAM plugin is installed and configured only if the + CNI plugin is set to Calico, for all other values of the + CNI plugin the plugin binaries and CNI config is a dependency + that is expected to be installed separately. \n Default: + Calico" + enum: + - Calico + - HostLocal + - AmazonVPC + - AzureVNET + type: string + required: + - type + type: object + type: + description: "Specifies the CNI plugin that will be used in the + Calico or Calico Enterprise installation. * For KubernetesProvider + GKE, this field defaults to GKE. * For KubernetesProvider AKS, + this field defaults to AzureVNET. * For KubernetesProvider EKS, + this field defaults to AmazonVPC. * If aws-node daemonset exists + in kube-system when the Installation resource is created, this + field defaults to AmazonVPC. * For all other cases this field + defaults to Calico. \n For the value Calico, the CNI plugin + binaries and CNI config will be installed as part of deployment, + for all other values the CNI plugin binaries and CNI config + is a dependency that is expected to be installed separately. + \n Default: Calico" + enum: + - Calico + - GKE + - AmazonVPC + - AzureVNET + type: string + required: + - type + type: object + componentResources: + description: Deprecated. Please use CalicoNodeDaemonSet, TyphaDeployment, + and KubeControllersDeployment. ComponentResources can be used to + customize the resource requirements for each component. Node, Typha, + and KubeControllers are supported for installations. + items: + description: Deprecated. Please use component resource config fields + in Installation.Spec instead. The ComponentResource struct associates + a ResourceRequirements with a component by name + properties: + componentName: + description: ComponentName is an enum which identifies the component + enum: + - Node + - Typha + - KubeControllers + type: string + resourceRequirements: + description: ResourceRequirements allows customization of limits + and requests for compute resources such as cpu and memory. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. More info: + https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - componentName + - resourceRequirements + type: object + type: array + controlPlaneNodeSelector: + additionalProperties: + type: string + description: ControlPlaneNodeSelector is used to select control plane + nodes on which to run Calico components. This is globally applied + to all resources created by the operator excluding daemonsets. + type: object + controlPlaneReplicas: + description: ControlPlaneReplicas defines how many replicas of the + control plane core components will be deployed. This field applies + to all control plane components that support High Availability. + Defaults to 2. + format: int32 + type: integer + controlPlaneTolerations: + description: ControlPlaneTolerations specify tolerations which are + then globally applied to all resources created by the operator. + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + flexVolumePath: + description: FlexVolumePath optionally specifies a custom path for + FlexVolume. If not specified, FlexVolume will be enabled by default. + If set to 'None', FlexVolume will be disabled. The default is based + on the kubernetesProvider. + type: string + imagePath: + description: "ImagePath allows for the path part of an image to be + specified. If specified then the specified value will be used as + the image path for each image. If not specified or empty, the default + for each image will be used. A special case value, UseDefault, is + supported to explicitly specify the default image path will be used + for each image. \n Image format: `/:` + \n This option allows configuring the `` portion of the + above format." + type: string + imagePrefix: + description: "ImagePrefix allows for the prefix part of an image to + be specified. If specified then the given value will be used as + a prefix on each image. If not specified or empty, no prefix will + be used. A special case value, UseDefault, is supported to explicitly + specify the default image prefix will be used for each image. \n + Image format: `/:` + \n This option allows configuring the `` portion of + the above format." + type: string + imagePullSecrets: + description: ImagePullSecrets is an array of references to container + registry pull secrets to use. These are applied to all images to + be pulled. + items: + description: LocalObjectReference contains enough information to + let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + kubernetesProvider: + description: KubernetesProvider specifies a particular provider of + the Kubernetes platform and enables provider-specific configuration. + If the specified value is empty, the Operator will attempt to automatically + determine the current provider. If the specified value is not empty, + the Operator will still attempt auto-detection, but will additionally + compare the auto-detected value to the specified value to confirm + they match. + enum: + - "" + - EKS + - GKE + - AKS + - OpenShift + - DockerEnterprise + - RKE2 + type: string + nodeMetricsPort: + description: NodeMetricsPort specifies which port calico/node serves + prometheus metrics on. By default, metrics are not enabled. If specified, + this overrides any FelixConfiguration resources which may exist. + If omitted, then prometheus metrics may still be configured through + FelixConfiguration. + format: int32 + type: integer + nodeUpdateStrategy: + description: NodeUpdateStrategy can be used to customize the desired + update strategy, such as the MaxUnavailable field. + properties: + rollingUpdate: + description: 'Rolling update config params. Present only if type + = "RollingUpdate". --- TODO: Update this to follow our convention + for oneOf, whatever we decide it to be. Same as Deployment `strategy.rollingUpdate`. + See https://github.com/kubernetes/kubernetes/issues/35345' + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of nodes with an existing + available DaemonSet pod that can have an updated DaemonSet + pod during during an update. Value can be an absolute number + (ex: 5) or a percentage of desired pods (ex: 10%). This + can not be 0 if MaxUnavailable is 0. Absolute number is + calculated from percentage by rounding up to a minimum of + 1. Default value is 0. Example: when this is set to 30%, + at most 30% of the total number of nodes that should be + running the daemon pod (i.e. status.desiredNumberScheduled) + can have their a new pod created before the old pod is marked + as deleted. The update starts by launching new pods on 30% + of nodes. Once an updated pod is available (Ready for at + least minReadySeconds) the old DaemonSet pod on that node + is marked deleted. If the old pod becomes unavailable for + any reason (Ready transitions to false, is evicted, or is + drained) an updated pod is immediatedly created on that + node without considering surge limits. Allowing surge implies + the possibility that the resources consumed by the daemonset + on any given node can double if the readiness check fails, + and so resource intensive daemonsets should take into account + that they may cause evictions during disruption. This is + an alpha field and requires enabling DaemonSetUpdateSurge + feature gate.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of DaemonSet pods that can + be unavailable during the update. Value can be an absolute + number (ex: 5) or a percentage of total number of DaemonSet + pods at the start of the update (ex: 10%). Absolute number + is calculated from percentage by rounding down to a minimum + of one. This cannot be 0 if MaxSurge is 0 Default value + is 1. Example: when this is set to 30%, at most 30% of the + total number of nodes that should be running the daemon + pod (i.e. status.desiredNumberScheduled) can have their + pods stopped for an update at any given time. The update + starts by stopping at most 30% of those DaemonSet pods and + then brings up new DaemonSet pods in their place. Once the + new pods are available, it then proceeds onto other DaemonSet + pods, thus ensuring that at least 70% of original number + of DaemonSet pods are available at all times during the + update.' + x-kubernetes-int-or-string: true + type: object + type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. + type: string + type: object + nonPrivileged: + description: NonPrivileged configures Calico to be run in non-privileged + containers as non-root users where possible. + type: string + registry: + description: "Registry is the default Docker registry used for component + Docker images. If specified then the given value must end with a + slash character (`/`) and all images will be pulled from this registry. + If not specified then the default registries will be used. A special + case value, UseDefault, is supported to explicitly specify the default + registries will be used. \n Image format: `/:` + \n This option allows configuring the `` portion of the + above format." + type: string + typhaAffinity: + description: Deprecated. Please use Installation.Spec.TyphaDeployment + instead. TyphaAffinity allows configuration of node affinity characteristics + for Typha pods. + properties: + nodeAffinity: + description: NodeAffinity describes node affinity scheduling rules + for typha. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: 'WARNING: Please note that if the affinity requirements + specified by this field are not met at scheduling time, + the pod will NOT be scheduled onto the node. There is no + fallback to another affinity rules with this setting. This + may cause networking disruption or even catastrophic failure! + PreferredDuringSchedulingIgnoredDuringExecution should be + used for affinity unless there is a specific well understood + reason to use RequiredDuringSchedulingIgnoredDuringExecution + and you can guarantee that the RequiredDuringSchedulingIgnoredDuringExecution + will always have sufficient nodes to satisfy the requirement. + NOTE: RequiredDuringSchedulingIgnoredDuringExecution is + set by default for AKS nodes, to avoid scheduling Typhas + on virtual-nodes. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node.' + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + type: object + typhaDeployment: + description: TyphaDeployment configures the typha Deployment. If used + in conjunction with the deprecated ComponentResources or TyphaAffinity, + then these overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's metadata + that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to the + object's annotations provided the key does not already exist + in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values that + may match replicaset and service selectors. Each of these + key/value pairs are added to the object's labels provided + the key does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the specification of the typha Deployment. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of seconds + for which a newly created Deployment pod should be ready + without any of its container crashing, for it to be considered + available. If specified, this overrides any minReadySeconds + value that may be set on the typha Deployment. If omitted, + the typha Deployment will use its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the typha Deployment pod that + will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added + to the object's annotations provided the key does + not already exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. + Each of these key/value pairs are added to the object's + labels provided the key does not already exist in + the object's labels. + type: object + type: object + spec: + description: Spec is the typha Deployment's PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity scheduling + rules for the typha pods. If specified, this overrides + any affinity that may be set on the typha Deployment. + If omitted, the typha Deployment will use its default + value for affinity. If used in conjunction with + the deprecated TyphaAffinity, then this value takes + precedence. WARNING: Please note that this field + will override the default calico-typha Deployment + affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the + most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null preferred + scheduling term matches no objects (i.e. + is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node selector + term matches no objects. The requirements + of them are ANDed. The TopologySelectorTerm + type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector + requirements by node's labels. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector + requirements by node's fields. + items: + description: A node selector requirement + is a selector that contains + values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key + that the selector applies + to. + type: string + operator: + description: Represents a + key's relationship to a + set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string + values. If the operator + is In or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the values + array must be empty. If + the operator is Gt or Lt, + the values array must have + a single element, which + will be interpreted as an + integer. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same node, + zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + affinity expressions specified by this field, + but it may choose a node that violates one + or more of the expressions. The node that + is most preferred is the one with the greatest + sum of weights, i.e. for each node that + meets all of the scheduling requirements + (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum + by iterating through the elements of this + field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest + sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the affinity requirements specified + by this field cease to be met at some point + during pod execution (e.g. due to a pod + label update), the system may or may not + try to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to + schedule pods to nodes that satisfy the + anti-affinity expressions specified by this + field, but it may choose a node that violates + one or more of the expressions. The node + that is most preferred is the one with the + greatest sum of weights, i.e. for each node + that meets all of the scheduling requirements + (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute + a sum by iterating through the elements + of this field and adding "weight" to the + sum if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the matched + WeightedPodAffinityTerm fields are added + per-node to find the most preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met at scheduling + time, the pod will not be scheduled onto + the node. If the anti-affinity requirements + specified by this field cease to be met + at some point during pod execution (e.g. + due to a pod label update), the system may + or may not try to eventually evict the pod + from its node. When there are multiple elements, + the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all + terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this pod + should be co-located (affinity) or not + co-located (anti-affinity) with, where + co-located is defined as running on a + node whose value of the label with key + matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set + of resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over the + set of namespaces that the term applies + to. The term is applied to the union + of the namespaces selected by this + field and the ones listed in the namespaces + field. null selector and null or empty + namespaces list means "this pod's + namespace". An empty selector ({}) + matches all namespaces. This field + is alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions is + a list of label selector requirements. + The requirements are ANDed. + items: + description: A label selector + requirement is a selector that + contains values, a key, and + an operator that relates the + key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to + a set of values. Valid operators + are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an + array of string values. + If the operator is In or + NotIn, the values array + must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be + empty. This array is replaced + during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map + of {key,value} pairs. A single + {key,value} in the matchLabels + map is equivalent to an element + of matchExpressions, whose key + field is "key", the operator is + "In", and the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies a + static list of namespace names that + the term applies to. The term is applied + to the union of the namespaces listed + in this field and the ones selected + by namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where + co-located is defined as running on + a node whose value of the label with + key topologyKey matches that of any + node on which any of the selected + pods is running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of typha containers. + If specified, this overrides the specified typha + Deployment containers. If omitted, the typha Deployment + will use its default values for its containers. + items: + description: TyphaDeploymentContainer is a typha + Deployment container. + properties: + name: + description: Name is an enum which identifies + the typha Deployment container by name. + enum: + - calico-typha + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named typha Deployment container's + resources. If omitted, the typha Deployment + will use its default value for this container's + resources. If used in conjunction with the + deprecated ComponentResources, then this value + takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + initContainers: + description: InitContainers is a list of typha init + containers. If specified, this overrides the specified + typha Deployment init containers. If omitted, the + typha Deployment will use its default values for + its init containers. + items: + description: TyphaDeploymentInitContainer is a typha + Deployment init container. + properties: + name: + description: Name is an enum which identifies + the typha Deployment init container by name. + enum: + - typha-certs-key-cert-provisioner + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, this + overrides the named typha Deployment init + container's resources. If omitted, the typha + Deployment will use its default value for + this init container's resources. If used in + conjunction with the deprecated ComponentResources, + then this value takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. More + info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum + amount of compute resources required. + If Requests is omitted for a container, + it defaults to Limits if that is explicitly + specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-typha pod''s + scheduling constraints. If specified, each of the + key/value pairs are added to the calico-typha Deployment + nodeSelector provided the key does not already exist + in the object''s nodeSelector. If omitted, the calico-typha + Deployment will use its default value for nodeSelector. + WARNING: Please note that this field will modify + the default calico-typha Deployment nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the typha pod''s tolerations. + If specified, this overrides any tolerations that + may be set on the typha Deployment. If omitted, + the typha Deployment will use its default value + for tolerations. WARNING: Please note that this + field will override the default calico-typha Deployment + tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint effect + to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, + PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; + this combination means to match all values + and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and + Equal. Defaults to Equal. Exists is equivalent + to wildcard for value, so that a pod can tolerate + all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the + period of time the toleration (which must + be of effect NoExecute, otherwise this field + is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint + forever (do not evict). Zero and negative + values will be treated as 0 (evict immediately) + by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the + value should be empty, otherwise just a regular + string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + typhaMetricsPort: + description: TyphaMetricsPort specifies which port calico/typha serves + prometheus metrics on. By default, metrics are not enabled. + format: int32 + type: integer + variant: + description: 'Variant is the product to install - one of Calico or + TigeraSecureEnterprise Default: Calico' + enum: + - Calico + - TigeraSecureEnterprise + type: string + type: object + status: + description: Most recently observed state for the Calico or Calico Enterprise + installation. + properties: + computed: + description: Computed is the final installation including overlaid + resources. + properties: + calicoKubeControllersDeployment: + description: CalicoKubeControllersDeployment configures the calico-kube-controllers + Deployment. If used in conjunction with the deprecated ComponentResources, + then these overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to + the object's annotations provided the key does not already + exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. Each + of these key/value pairs are added to the object's labels + provided the key does not already exist in the object's + labels. + type: object + type: object + spec: + description: Spec is the specification of the calico-kube-controllers + Deployment. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of + seconds for which a newly created Deployment pod should + be ready without any of its container crashing, for + it to be considered available. If specified, this overrides + any minReadySeconds value that may be set on the calico-kube-controllers + Deployment. If omitted, the calico-kube-controllers + Deployment will use its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the calico-kube-controllers + Deployment pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes + object's metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary + non-identifying metadata. Each of these key/value + pairs are added to the object's annotations + provided the key does not already exist in the + object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and + values that may match replicaset and service + selectors. Each of these key/value pairs are + added to the object's labels provided the key + does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the calico-kube-controllers Deployment's + PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity + scheduling rules for the calico-kube-controllers + pods. If specified, this overrides any affinity + that may be set on the calico-kube-controllers + Deployment. If omitted, the calico-kube-controllers + Deployment will use its default value for affinity. + WARNING: Please note that this field will override + the default calico-kube-controllers Deployment + affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node matches the corresponding + matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, + associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node + selector term matches no objects. + The requirements of them are ANDed. + The TopologySelectorTerm type + implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the + same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the anti-affinity expressions specified + by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the anti-affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of calico-kube-controllers + containers. If specified, this overrides the + specified calico-kube-controllers Deployment + containers. If omitted, the calico-kube-controllers + Deployment will use its default values for its + containers. + items: + description: CalicoKubeControllersDeploymentContainer + is a calico-kube-controllers Deployment container. + properties: + name: + description: Name is an enum which identifies + the calico-kube-controllers Deployment + container by name. + enum: + - calico-kube-controllers + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, + this overrides the named calico-kube-controllers + Deployment container's resources. If omitted, + the calico-kube-controllers Deployment + will use its default value for this container's + resources. If used in conjunction with + the deprecated ComponentResources, then + this value takes precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-kube-controllers + pod''s scheduling constraints. If specified, + each of the key/value pairs are added to the + calico-kube-controllers Deployment nodeSelector + provided the key does not already exist in the + object''s nodeSelector. If used in conjunction + with ControlPlaneNodeSelector, that nodeSelector + is set on the calico-kube-controllers Deployment + and each of this field''s key/value pairs are + added to the calico-kube-controllers Deployment + nodeSelector provided the key does not already + exist in the object''s nodeSelector. If omitted, + the calico-kube-controllers Deployment will + use its default value for nodeSelector. WARNING: + Please note that this field will modify the + default calico-kube-controllers Deployment nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the calico-kube-controllers + pod''s tolerations. If specified, this overrides + any tolerations that may be set on the calico-kube-controllers + Deployment. If omitted, the calico-kube-controllers + Deployment will use its default value for tolerations. + WARNING: Please note that this field will override + the default calico-kube-controllers Deployment + tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint + effect to match. Empty means match all + taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Key is the taint key that the + toleration applies to. Empty means match + all taint keys. If the key is empty, operator + must be Exists; this combination means + to match all values and all keys. + type: string + operator: + description: Operator represents a key's + relationship to the value. Valid operators + are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints + of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents + the period of time the toleration (which + must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. + By default, it is not set, which means + tolerate the taint forever (do not evict). + Zero and negative values will be treated + as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the + toleration matches to. If the operator + is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + calicoNetwork: + description: CalicoNetwork specifies networking configuration + options for Calico. + properties: + bgp: + description: BGP configures whether or not to enable Calico's + BGP capabilities. + enum: + - Enabled + - Disabled + type: string + containerIPForwarding: + description: 'ContainerIPForwarding configures whether ip + forwarding will be enabled for containers in the CNI configuration. + Default: Disabled' + enum: + - Enabled + - Disabled + type: string + hostPorts: + description: 'HostPorts configures whether or not Calico will + support Kubernetes HostPorts. Valid only when using the + Calico CNI plugin. Default: Enabled' + enum: + - Enabled + - Disabled + type: string + ipPools: + description: IPPools contains a list of IP pools to create + if none exist. At most one IP pool of each address family + may be specified. If omitted, a single pool will be configured + if needed. + items: + properties: + blockSize: + description: 'BlockSize specifies the CIDR prefex length + to use when allocating per-node IP blocks from the + main IP pool CIDR. Default: 26 (IPv4), 122 (IPv6)' + format: int32 + type: integer + cidr: + description: CIDR contains the address range for the + IP Pool in classless inter-domain routing format. + type: string + disableBGPExport: + default: false + description: 'DisableBGPExport specifies whether routes + from this IP pool''s CIDR are exported over BGP. Default: + false' + type: boolean + encapsulation: + description: 'Encapsulation specifies the encapsulation + type that will be used with the IP Pool. Default: + IPIP' + enum: + - IPIPCrossSubnet + - IPIP + - VXLAN + - VXLANCrossSubnet + - None + type: string + natOutgoing: + description: 'NATOutgoing specifies if NAT will be enabled + or disabled for outgoing traffic. Default: Enabled' + enum: + - Enabled + - Disabled + type: string + nodeSelector: + description: 'NodeSelector specifies the node selector + that will be set for the IP Pool. Default: ''all()''' + type: string + required: + - cidr + type: object + type: array + linuxDataplane: + description: 'LinuxDataplane is used to select the dataplane + used for Linux nodes. In particular, it causes the operator + to add required mounts and environment variables for the + particular dataplane. If not specified, iptables mode is + used. Default: Iptables' + enum: + - Iptables + - BPF + - VPP + type: string + mtu: + description: MTU specifies the maximum transmission unit to + use on the pod network. If not specified, Calico will perform + MTU auto-detection based on the cluster network. + format: int32 + type: integer + multiInterfaceMode: + description: 'MultiInterfaceMode configures what will configure + multiple interface per pod. Only valid for Calico Enterprise + installations using the Calico CNI plugin. Default: None' + enum: + - None + - Multus + type: string + nodeAddressAutodetectionV4: + description: NodeAddressAutodetectionV4 specifies an approach + to automatically detect node IPv4 addresses. If not specified, + will use default auto-detection settings to acquire an IPv4 + address for each node. + properties: + canReach: + description: CanReach enables IP auto-detection based + on which source address on the node is used to reach + the specified IP or domain. + type: string + cidrs: + description: CIDRS enables IP auto-detection based on + which addresses on the nodes are within one of the provided + CIDRs. + items: + type: string + type: array + firstFound: + description: FirstFound uses default interface matching + parameters to select an interface, performing best-effort + filtering based on well-known interface names. + type: boolean + interface: + description: Interface enables IP auto-detection based + on interfaces that match the given regex. + type: string + kubernetes: + description: Kubernetes configures Calico to detect node + addresses based on the Kubernetes API. + enum: + - NodeInternalIP + type: string + skipInterface: + description: SkipInterface enables IP auto-detection based + on interfaces that do not match the given regex. + type: string + type: object + nodeAddressAutodetectionV6: + description: NodeAddressAutodetectionV6 specifies an approach + to automatically detect node IPv6 addresses. If not specified, + IPv6 addresses will not be auto-detected. + properties: + canReach: + description: CanReach enables IP auto-detection based + on which source address on the node is used to reach + the specified IP or domain. + type: string + cidrs: + description: CIDRS enables IP auto-detection based on + which addresses on the nodes are within one of the provided + CIDRs. + items: + type: string + type: array + firstFound: + description: FirstFound uses default interface matching + parameters to select an interface, performing best-effort + filtering based on well-known interface names. + type: boolean + interface: + description: Interface enables IP auto-detection based + on interfaces that match the given regex. + type: string + kubernetes: + description: Kubernetes configures Calico to detect node + addresses based on the Kubernetes API. + enum: + - NodeInternalIP + type: string + skipInterface: + description: SkipInterface enables IP auto-detection based + on interfaces that do not match the given regex. + type: string + type: object + type: object + calicoNodeDaemonSet: + description: CalicoNodeDaemonSet configures the calico-node DaemonSet. + If used in conjunction with the deprecated ComponentResources, + then these overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the DaemonSet. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to + the object's annotations provided the key does not already + exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. Each + of these key/value pairs are added to the object's labels + provided the key does not already exist in the object's + labels. + type: object + type: object + spec: + description: Spec is the specification of the calico-node + DaemonSet. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of + seconds for which a newly created DaemonSet pod should + be ready without any of its container crashing, for + it to be considered available. If specified, this overrides + any minReadySeconds value that may be set on the calico-node + DaemonSet. If omitted, the calico-node DaemonSet will + use its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the calico-node DaemonSet + pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes + object's metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary + non-identifying metadata. Each of these key/value + pairs are added to the object's annotations + provided the key does not already exist in the + object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and + values that may match replicaset and service + selectors. Each of these key/value pairs are + added to the object's labels provided the key + does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the calico-node DaemonSet's PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity + scheduling rules for the calico-node pods. If + specified, this overrides any affinity that + may be set on the calico-node DaemonSet. If + omitted, the calico-node DaemonSet will use + its default value for affinity. WARNING: Please + note that this field will override the default + calico-node DaemonSet affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node matches the corresponding + matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, + associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node + selector term matches no objects. + The requirements of them are ANDed. + The TopologySelectorTerm type + implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the + same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the anti-affinity expressions specified + by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the anti-affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of calico-node + containers. If specified, this overrides the + specified calico-node DaemonSet containers. + If omitted, the calico-node DaemonSet will use + its default values for its containers. + items: + description: CalicoNodeDaemonSetContainer is + a calico-node DaemonSet container. + properties: + name: + description: Name is an enum which identifies + the calico-node DaemonSet container by + name. + enum: + - calico-node + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, + this overrides the named calico-node DaemonSet + container's resources. If omitted, the + calico-node DaemonSet will use its default + value for this container's resources. + If used in conjunction with the deprecated + ComponentResources, then this value takes + precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + initContainers: + description: InitContainers is a list of calico-node + init containers. If specified, this overrides + the specified calico-node DaemonSet init containers. + If omitted, the calico-node DaemonSet will use + its default values for its init containers. + items: + description: CalicoNodeDaemonSetInitContainer + is a calico-node DaemonSet init container. + properties: + name: + description: Name is an enum which identifies + the calico-node DaemonSet init container + by name. + enum: + - install-cni + - hostpath-init + - flexvol-driver + - mount-bpffs + - node-certs-key-cert-provisioner + - calico-node-prometheus-server-tls-key-cert-provisioner + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, + this overrides the named calico-node DaemonSet + init container's resources. If omitted, + the calico-node DaemonSet will use its + default value for this container's resources. + If used in conjunction with the deprecated + ComponentResources, then this value takes + precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-node + pod''s scheduling constraints. If specified, + each of the key/value pairs are added to the + calico-node DaemonSet nodeSelector provided + the key does not already exist in the object''s + nodeSelector. If omitted, the calico-node DaemonSet + will use its default value for nodeSelector. + WARNING: Please note that this field will modify + the default calico-node DaemonSet nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the calico-node pod''s + tolerations. If specified, this overrides any + tolerations that may be set on the calico-node + DaemonSet. If omitted, the calico-node DaemonSet + will use its default value for tolerations. + WARNING: Please note that this field will override + the default calico-node DaemonSet tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint + effect to match. Empty means match all + taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Key is the taint key that the + toleration applies to. Empty means match + all taint keys. If the key is empty, operator + must be Exists; this combination means + to match all values and all keys. + type: string + operator: + description: Operator represents a key's + relationship to the value. Valid operators + are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints + of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents + the period of time the toleration (which + must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. + By default, it is not set, which means + tolerate the taint forever (do not evict). + Zero and negative values will be treated + as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the + toleration matches to. If the operator + is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + calicoWindowsUpgradeDaemonSet: + description: CalicoWindowsUpgradeDaemonSet configures the calico-windows-upgrade + DaemonSet. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to + the object's annotations provided the key does not already + exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. Each + of these key/value pairs are added to the object's labels + provided the key does not already exist in the object's + labels. + type: object + type: object + spec: + description: Spec is the specification of the calico-windows-upgrade + DaemonSet. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of + seconds for which a newly created Deployment pod should + be ready without any of its container crashing, for + it to be considered available. If specified, this overrides + any minReadySeconds value that may be set on the calico-windows-upgrade + DaemonSet. If omitted, the calico-windows-upgrade DaemonSet + will use its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the calico-windows-upgrade + DaemonSet pod that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes + object's metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary + non-identifying metadata. Each of these key/value + pairs are added to the object's annotations + provided the key does not already exist in the + object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and + values that may match replicaset and service + selectors. Each of these key/value pairs are + added to the object's labels provided the key + does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the calico-windows-upgrade DaemonSet's + PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity + scheduling rules for the calico-windows-upgrade + pods. If specified, this overrides any affinity + that may be set on the calico-windows-upgrade + DaemonSet. If omitted, the calico-windows-upgrade + DaemonSet will use its default value for affinity. + WARNING: Please note that this field will override + the default calico-windows-upgrade DaemonSet + affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node matches the corresponding + matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, + associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node + selector term matches no objects. + The requirements of them are ANDed. + The TopologySelectorTerm type + implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the + same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the anti-affinity expressions specified + by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the anti-affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of calico-windows-upgrade + containers. If specified, this overrides the + specified calico-windows-upgrade DaemonSet containers. + If omitted, the calico-windows-upgrade DaemonSet + will use its default values for its containers. + items: + description: CalicoWindowsUpgradeDaemonSetContainer + is a calico-windows-upgrade DaemonSet container. + properties: + name: + description: Name is an enum which identifies + the calico-windows-upgrade DaemonSet container + by name. + enum: + - calico-windows-upgrade + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, + this overrides the named calico-windows-upgrade + DaemonSet container's resources. If omitted, + the calico-windows-upgrade DaemonSet will + use its default value for this container's + resources. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-windows-upgrade + pod''s scheduling constraints. If specified, + each of the key/value pairs are added to the + calico-windows-upgrade DaemonSet nodeSelector + provided the key does not already exist in the + object''s nodeSelector. If omitted, the calico-windows-upgrade + DaemonSet will use its default value for nodeSelector. + WARNING: Please note that this field will modify + the default calico-windows-upgrade DaemonSet + nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the calico-windows-upgrade + pod''s tolerations. If specified, this overrides + any tolerations that may be set on the calico-windows-upgrade + DaemonSet. If omitted, the calico-windows-upgrade + DaemonSet will use its default value for tolerations. + WARNING: Please note that this field will override + the default calico-windows-upgrade DaemonSet + tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint + effect to match. Empty means match all + taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Key is the taint key that the + toleration applies to. Empty means match + all taint keys. If the key is empty, operator + must be Exists; this combination means + to match all values and all keys. + type: string + operator: + description: Operator represents a key's + relationship to the value. Valid operators + are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints + of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents + the period of time the toleration (which + must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. + By default, it is not set, which means + tolerate the taint forever (do not evict). + Zero and negative values will be treated + as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the + toleration matches to. If the operator + is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + certificateManagement: + description: CertificateManagement configures pods to submit a + CertificateSigningRequest to the certificates.k8s.io/v1beta1 + API in order to obtain TLS certificates. This feature requires + that you bring your own CSR signing and approval process, otherwise + pods will be stuck during initialization. + properties: + caCert: + description: Certificate of the authority that signs the CertificateSigningRequests + in PEM format. + format: byte + type: string + keyAlgorithm: + description: 'Specify the algorithm used by pods to generate + a key pair that is associated with the X.509 certificate + request. Default: RSAWithSize2048' + enum: + - "" + - RSAWithSize2048 + - RSAWithSize4096 + - RSAWithSize8192 + - ECDSAWithCurve256 + - ECDSAWithCurve384 + - ECDSAWithCurve521 + type: string + signatureAlgorithm: + description: 'Specify the algorithm used for the signature + of the X.509 certificate request. Default: SHA256WithRSA' + enum: + - "" + - SHA256WithRSA + - SHA384WithRSA + - SHA512WithRSA + - ECDSAWithSHA256 + - ECDSAWithSHA384 + - ECDSAWithSHA512 + type: string + signerName: + description: 'When a CSR is issued to the certificates.k8s.io + API, the signerName is added to the request in order to + accommodate for clusters with multiple signers. Must be + formatted as: `/`.' + type: string + required: + - caCert + - signerName + type: object + cni: + description: CNI specifies the CNI that will be used by this installation. + properties: + ipam: + description: IPAM specifies the pod IP address management + that will be used in the Calico or Calico Enterprise installation. + properties: + type: + description: "Specifies the IPAM plugin that will be used + in the Calico or Calico Enterprise installation. * For + CNI Plugin Calico, this field defaults to Calico. * + For CNI Plugin GKE, this field defaults to HostLocal. + * For CNI Plugin AzureVNET, this field defaults to AzureVNET. + * For CNI Plugin AmazonVPC, this field defaults to AmazonVPC. + \n The IPAM plugin is installed and configured only + if the CNI plugin is set to Calico, for all other values + of the CNI plugin the plugin binaries and CNI config + is a dependency that is expected to be installed separately. + \n Default: Calico" + enum: + - Calico + - HostLocal + - AmazonVPC + - AzureVNET + type: string + required: + - type + type: object + type: + description: "Specifies the CNI plugin that will be used in + the Calico or Calico Enterprise installation. * For KubernetesProvider + GKE, this field defaults to GKE. * For KubernetesProvider + AKS, this field defaults to AzureVNET. * For KubernetesProvider + EKS, this field defaults to AmazonVPC. * If aws-node daemonset + exists in kube-system when the Installation resource is + created, this field defaults to AmazonVPC. * For all other + cases this field defaults to Calico. \n For the value Calico, + the CNI plugin binaries and CNI config will be installed + as part of deployment, for all other values the CNI plugin + binaries and CNI config is a dependency that is expected + to be installed separately. \n Default: Calico" + enum: + - Calico + - GKE + - AmazonVPC + - AzureVNET + type: string + required: + - type + type: object + componentResources: + description: Deprecated. Please use CalicoNodeDaemonSet, TyphaDeployment, + and KubeControllersDeployment. ComponentResources can be used + to customize the resource requirements for each component. Node, + Typha, and KubeControllers are supported for installations. + items: + description: Deprecated. Please use component resource config + fields in Installation.Spec instead. The ComponentResource + struct associates a ResourceRequirements with a component + by name + properties: + componentName: + description: ComponentName is an enum which identifies the + component + enum: + - Node + - Typha + - KubeControllers + type: string + resourceRequirements: + description: ResourceRequirements allows customization of + limits and requests for compute resources such as cpu + and memory. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of + compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - componentName + - resourceRequirements + type: object + type: array + controlPlaneNodeSelector: + additionalProperties: + type: string + description: ControlPlaneNodeSelector is used to select control + plane nodes on which to run Calico components. This is globally + applied to all resources created by the operator excluding daemonsets. + type: object + controlPlaneReplicas: + description: ControlPlaneReplicas defines how many replicas of + the control plane core components will be deployed. This field + applies to all control plane components that support High Availability. + Defaults to 2. + format: int32 + type: integer + controlPlaneTolerations: + description: ControlPlaneTolerations specify tolerations which + are then globally applied to all resources created by the operator. + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + flexVolumePath: + description: FlexVolumePath optionally specifies a custom path + for FlexVolume. If not specified, FlexVolume will be enabled + by default. If set to 'None', FlexVolume will be disabled. The + default is based on the kubernetesProvider. + type: string + imagePath: + description: "ImagePath allows for the path part of an image to + be specified. If specified then the specified value will be + used as the image path for each image. If not specified or empty, + the default for each image will be used. A special case value, + UseDefault, is supported to explicitly specify the default image + path will be used for each image. \n Image format: `/:` + \n This option allows configuring the `` portion + of the above format." + type: string + imagePrefix: + description: "ImagePrefix allows for the prefix part of an image + to be specified. If specified then the given value will be used + as a prefix on each image. If not specified or empty, no prefix + will be used. A special case value, UseDefault, is supported + to explicitly specify the default image prefix will be used + for each image. \n Image format: `/:` + \n This option allows configuring the `` portion + of the above format." + type: string + imagePullSecrets: + description: ImagePullSecrets is an array of references to container + registry pull secrets to use. These are applied to all images + to be pulled. + items: + description: LocalObjectReference contains enough information + to let you locate the referenced object inside the same namespace. + properties: + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, uid?' + type: string + type: object + type: array + kubernetesProvider: + description: KubernetesProvider specifies a particular provider + of the Kubernetes platform and enables provider-specific configuration. + If the specified value is empty, the Operator will attempt to + automatically determine the current provider. If the specified + value is not empty, the Operator will still attempt auto-detection, + but will additionally compare the auto-detected value to the + specified value to confirm they match. + enum: + - "" + - EKS + - GKE + - AKS + - OpenShift + - DockerEnterprise + - RKE2 + type: string + nodeMetricsPort: + description: NodeMetricsPort specifies which port calico/node + serves prometheus metrics on. By default, metrics are not enabled. + If specified, this overrides any FelixConfiguration resources + which may exist. If omitted, then prometheus metrics may still + be configured through FelixConfiguration. + format: int32 + type: integer + nodeUpdateStrategy: + description: NodeUpdateStrategy can be used to customize the desired + update strategy, such as the MaxUnavailable field. + properties: + rollingUpdate: + description: 'Rolling update config params. Present only if + type = "RollingUpdate". --- TODO: Update this to follow + our convention for oneOf, whatever we decide it to be. Same + as Deployment `strategy.rollingUpdate`. See https://github.com/kubernetes/kubernetes/issues/35345' + properties: + maxSurge: + anyOf: + - type: integer + - type: string + description: 'The maximum number of nodes with an existing + available DaemonSet pod that can have an updated DaemonSet + pod during during an update. Value can be an absolute + number (ex: 5) or a percentage of desired pods (ex: + 10%). This can not be 0 if MaxUnavailable is 0. Absolute + number is calculated from percentage by rounding up + to a minimum of 1. Default value is 0. Example: when + this is set to 30%, at most 30% of the total number + of nodes that should be running the daemon pod (i.e. + status.desiredNumberScheduled) can have their a new + pod created before the old pod is marked as deleted. + The update starts by launching new pods on 30% of nodes. + Once an updated pod is available (Ready for at least + minReadySeconds) the old DaemonSet pod on that node + is marked deleted. If the old pod becomes unavailable + for any reason (Ready transitions to false, is evicted, + or is drained) an updated pod is immediatedly created + on that node without considering surge limits. Allowing + surge implies the possibility that the resources consumed + by the daemonset on any given node can double if the + readiness check fails, and so resource intensive daemonsets + should take into account that they may cause evictions + during disruption. This is an alpha field and requires + enabling DaemonSetUpdateSurge feature gate.' + x-kubernetes-int-or-string: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: 'The maximum number of DaemonSet pods that + can be unavailable during the update. Value can be an + absolute number (ex: 5) or a percentage of total number + of DaemonSet pods at the start of the update (ex: 10%). + Absolute number is calculated from percentage by rounding + down to a minimum of one. This cannot be 0 if MaxSurge + is 0 Default value is 1. Example: when this is set to + 30%, at most 30% of the total number of nodes that should + be running the daemon pod (i.e. status.desiredNumberScheduled) + can have their pods stopped for an update at any given + time. The update starts by stopping at most 30% of those + DaemonSet pods and then brings up new DaemonSet pods + in their place. Once the new pods are available, it + then proceeds onto other DaemonSet pods, thus ensuring + that at least 70% of original number of DaemonSet pods + are available at all times during the update.' + x-kubernetes-int-or-string: true + type: object + type: + description: Type of daemon set update. Can be "RollingUpdate" + or "OnDelete". Default is RollingUpdate. + type: string + type: object + nonPrivileged: + description: NonPrivileged configures Calico to be run in non-privileged + containers as non-root users where possible. + type: string + registry: + description: "Registry is the default Docker registry used for + component Docker images. If specified then the given value must + end with a slash character (`/`) and all images will be pulled + from this registry. If not specified then the default registries + will be used. A special case value, UseDefault, is supported + to explicitly specify the default registries will be used. \n + Image format: `/:` + \n This option allows configuring the `` portion of + the above format." + type: string + typhaAffinity: + description: Deprecated. Please use Installation.Spec.TyphaDeployment + instead. TyphaAffinity allows configuration of node affinity + characteristics for Typha pods. + properties: + nodeAffinity: + description: NodeAffinity describes node affinity scheduling + rules for typha. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: 'WARNING: Please note that if the affinity + requirements specified by this field are not met at + scheduling time, the pod will NOT be scheduled onto + the node. There is no fallback to another affinity rules + with this setting. This may cause networking disruption + or even catastrophic failure! PreferredDuringSchedulingIgnoredDuringExecution + should be used for affinity unless there is a specific + well understood reason to use RequiredDuringSchedulingIgnoredDuringExecution + and you can guarantee that the RequiredDuringSchedulingIgnoredDuringExecution + will always have sufficient nodes to satisfy the requirement. + NOTE: RequiredDuringSchedulingIgnoredDuringExecution + is set by default for AKS nodes, to avoid scheduling + Typhas on virtual-nodes. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node.' + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + type: object + typhaDeployment: + description: TyphaDeployment configures the typha Deployment. + If used in conjunction with the deprecated ComponentResources + or TyphaAffinity, then these overrides take precedence. + properties: + metadata: + description: Metadata is a subset of a Kubernetes object's + metadata that is added to the Deployment. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary non-identifying + metadata. Each of these key/value pairs are added to + the object's annotations provided the key does not already + exist in the object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and values + that may match replicaset and service selectors. Each + of these key/value pairs are added to the object's labels + provided the key does not already exist in the object's + labels. + type: object + type: object + spec: + description: Spec is the specification of the typha Deployment. + properties: + minReadySeconds: + description: MinReadySeconds is the minimum number of + seconds for which a newly created Deployment pod should + be ready without any of its container crashing, for + it to be considered available. If specified, this overrides + any minReadySeconds value that may be set on the typha + Deployment. If omitted, the typha Deployment will use + its default value for minReadySeconds. + format: int32 + maximum: 2147483647 + minimum: 0 + type: integer + template: + description: Template describes the typha Deployment pod + that will be created. + properties: + metadata: + description: Metadata is a subset of a Kubernetes + object's metadata that is added to the pod's metadata. + properties: + annotations: + additionalProperties: + type: string + description: Annotations is a map of arbitrary + non-identifying metadata. Each of these key/value + pairs are added to the object's annotations + provided the key does not already exist in the + object's annotations. + type: object + labels: + additionalProperties: + type: string + description: Labels is a map of string keys and + values that may match replicaset and service + selectors. Each of these key/value pairs are + added to the object's labels provided the key + does not already exist in the object's labels. + type: object + type: object + spec: + description: Spec is the typha Deployment's PodSpec. + properties: + affinity: + description: 'Affinity is a group of affinity + scheduling rules for the typha pods. If specified, + this overrides any affinity that may be set + on the typha Deployment. If omitted, the typha + Deployment will use its default value for affinity. + If used in conjunction with the deprecated TyphaAffinity, + then this value takes precedence. WARNING: Please + note that this field will override the default + calico-typha Deployment affinity.' + properties: + nodeAffinity: + description: Describes node affinity scheduling + rules for the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node matches the corresponding + matchExpressions; the node(s) with the + highest sum are the most preferred. + items: + description: An empty preferred scheduling + term matches all objects with implicit + weight 0 (i.e. it's a no-op). A null + preferred scheduling term matches + no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, + associated with the corresponding + weight. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + weight: + description: Weight associated with + matching the corresponding nodeSelectorTerm, + in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to an update), + the system may or may not try to eventually + evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node + selector terms. The terms are ORed. + items: + description: A null or empty node + selector term matches no objects. + The requirements of them are ANDed. + The TopologySelectorTerm type + implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node + selector requirements by node's + labels. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node + selector requirements by node's + fields. + items: + description: A node selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: The label + key that the selector + applies to. + type: string + operator: + description: Represents + a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array + of string values. If + the operator is In or + NotIn, the values array + must be non-empty. If + the operator is Exists + or DoesNotExist, the + values array must be + empty. If the operator + is Gt or Lt, the values + array must have a single + element, which will + be interpreted as an + integer. This array + is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + type: array + required: + - nodeSelectorTerms + type: object + type: object + podAffinity: + description: Describes pod affinity scheduling + rules (e.g. co-locate this pod in the same + node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the affinity expressions specified by + this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling + rules (e.g. avoid putting this pod in the + same node, zone, etc. as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer + to schedule pods to nodes that satisfy + the anti-affinity expressions specified + by this field, but it may choose a node + that violates one or more of the expressions. + The node that is most preferred is the + one with the greatest sum of weights, + i.e. for each node that meets all of + the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by + iterating through the elements of this + field and adding "weight" to the sum + if the node has pods which matches the + corresponding podAffinityTerm; the node(s) + with the highest sum are the most preferred. + items: + description: The weights of all of the + matched WeightedPodAffinityTerm fields + are added per-node to find the most + preferred node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity + term, associated with the corresponding + weight. + properties: + labelSelector: + description: A label query over + a set of resources, in this + case pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that + the term applies to. The term + is applied to the union of + the namespaces selected by + this field and the ones listed + in the namespaces field. null + selector and null or empty + namespaces list means "this + pod's namespace". An empty + selector ({}) matches all + namespaces. This field is + alpha-level and is only honored + when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, + a key, and an operator + that relates the key + and values. + properties: + key: + description: key is + the label key that + the selector applies + to. + type: string + operator: + description: operator + represents a key's + relationship to + a set of values. + Valid operators + are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values + is an array of string + values. If the operator + is In or NotIn, + the values array + must be non-empty. + If the operator + is Exists or DoesNotExist, + the values array + must be empty. This + array is replaced + during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels + is a map of {key,value} + pairs. A single {key,value} + in the matchLabels map + is equivalent to an element + of matchExpressions, whose + key field is "key", the + operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace + names that the term applies + to. The term is applied to + the union of the namespaces + listed in this field and the + ones selected by namespaceSelector. + null or empty namespaces list + and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should + be co-located (affinity) or + not co-located (anti-affinity) + with the pods matching the + labelSelector in the specified + namespaces, where co-located + is defined as running on a + node whose value of the label + with key topologyKey matches + that of any node on which + any of the selected pods is + running. Empty topologyKey + is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with + matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements + specified by this field are not met + at scheduling time, the pod will not + be scheduled onto the node. If the anti-affinity + requirements specified by this field + cease to be met at some point during + pod execution (e.g. due to a pod label + update), the system may or may not try + to eventually evict the pod from its + node. When there are multiple elements, + the lists of nodes corresponding to + each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely + those matching the labelSelector relative + to the given namespace(s)) that this + pod should be co-located (affinity) + or not co-located (anti-affinity) + with, where co-located is defined + as running on a node whose value of + the label with key matches + that of any node on which a pod of + the set of pods is running + properties: + labelSelector: + description: A label query over + a set of resources, in this case + pods. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaceSelector: + description: A label query over + the set of namespaces that the + term applies to. The term is applied + to the union of the namespaces + selected by this field and the + ones listed in the namespaces + field. null selector and null + or empty namespaces list means + "this pod's namespace". An empty + selector ({}) matches all namespaces. + This field is alpha-level and + is only honored when PodAffinityNamespaceSelector + feature is enabled. + properties: + matchExpressions: + description: matchExpressions + is a list of label selector + requirements. The requirements + are ANDed. + items: + description: A label selector + requirement is a selector + that contains values, a + key, and an operator that + relates the key and values. + properties: + key: + description: key is the + label key that the selector + applies to. + type: string + operator: + description: operator + represents a key's relationship + to a set of values. + Valid operators are + In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is + an array of string values. + If the operator is In + or NotIn, the values + array must be non-empty. + If the operator is Exists + or DoesNotExist, the + values array must be + empty. This array is + replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is + a map of {key,value} pairs. + A single {key,value} in the + matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", + the operator is "In", and + the values array contains + only "value". The requirements + are ANDed. + type: object + type: object + namespaces: + description: namespaces specifies + a static list of namespace names + that the term applies to. The + term is applied to the union of + the namespaces listed in this + field and the ones selected by + namespaceSelector. null or empty + namespaces list and null namespaceSelector + means "this pod's namespace" + items: + type: string + type: array + topologyKey: + description: This pod should be + co-located (affinity) or not co-located + (anti-affinity) with the pods + matching the labelSelector in + the specified namespaces, where + co-located is defined as running + on a node whose value of the label + with key topologyKey matches that + of any node on which any of the + selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + containers: + description: Containers is a list of typha containers. + If specified, this overrides the specified typha + Deployment containers. If omitted, the typha + Deployment will use its default values for its + containers. + items: + description: TyphaDeploymentContainer is a typha + Deployment container. + properties: + name: + description: Name is an enum which identifies + the typha Deployment container by name. + enum: + - calico-typha + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, + this overrides the named typha Deployment + container's resources. If omitted, the + typha Deployment will use its default + value for this container's resources. + If used in conjunction with the deprecated + ComponentResources, then this value takes + precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + initContainers: + description: InitContainers is a list of typha + init containers. If specified, this overrides + the specified typha Deployment init containers. + If omitted, the typha Deployment will use its + default values for its init containers. + items: + description: TyphaDeploymentInitContainer is + a typha Deployment init container. + properties: + name: + description: Name is an enum which identifies + the typha Deployment init container by + name. + enum: + - typha-certs-key-cert-provisioner + type: string + resources: + description: Resources allows customization + of limits and requests for compute resources + such as cpu and memory. If specified, + this overrides the named typha Deployment + init container's resources. If omitted, + the typha Deployment will use its default + value for this init container's resources. + If used in conjunction with the deprecated + ComponentResources, then this value takes + precedence. + properties: + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum + amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the + minimum amount of compute resources + required. If Requests is omitted for + a container, it defaults to Limits + if that is explicitly specified, otherwise + to an implementation-defined value. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + required: + - name + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is the calico-typha + pod''s scheduling constraints. If specified, + each of the key/value pairs are added to the + calico-typha Deployment nodeSelector provided + the key does not already exist in the object''s + nodeSelector. If omitted, the calico-typha Deployment + will use its default value for nodeSelector. + WARNING: Please note that this field will modify + the default calico-typha Deployment nodeSelector.' + type: object + tolerations: + description: 'Tolerations is the typha pod''s + tolerations. If specified, this overrides any + tolerations that may be set on the typha Deployment. + If omitted, the typha Deployment will use its + default value for tolerations. WARNING: Please + note that this field will override the default + calico-typha Deployment tolerations.' + items: + description: The pod this Toleration is attached + to tolerates any taint that matches the triple + using the matching operator + . + properties: + effect: + description: Effect indicates the taint + effect to match. Empty means match all + taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule + and NoExecute. + type: string + key: + description: Key is the taint key that the + toleration applies to. Empty means match + all taint keys. If the key is empty, operator + must be Exists; this combination means + to match all values and all keys. + type: string + operator: + description: Operator represents a key's + relationship to the value. Valid operators + are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints + of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents + the period of time the toleration (which + must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. + By default, it is not set, which means + tolerate the taint forever (do not evict). + Zero and negative values will be treated + as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the + toleration matches to. If the operator + is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + type: object + type: object + type: object + typhaMetricsPort: + description: TyphaMetricsPort specifies which port calico/typha + serves prometheus metrics on. By default, metrics are not enabled. + format: int32 + type: integer + variant: + description: 'Variant is the product to install - one of Calico + or TigeraSecureEnterprise Default: Calico' + enum: + - Calico + - TigeraSecureEnterprise + type: string + type: object + conditions: + description: Conditions represents the latest observed set of conditions + for the component. A component may be one or more of Ready, Progressing, + Degraded or other customer types. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: + \"Available\", \"Progressing\", and \"Degraded\" // +patchMergeKey=type + \ // +patchStrategy=merge // +listType=map // +listMapKey=type + \ Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` + \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + imageSet: + description: ImageSet is the name of the ImageSet being used, if there + is an ImageSet that is being used. If an ImageSet is not being used + then this will not be set. + type: string + mtu: + description: MTU is the most recently observed value for pod network + MTU. This may be an explicitly configured value, or based on Calico's + native auto-detetion. + format: int32 + type: integer + variant: + description: Variant is the most recently observed installed variant + - one of Calico or TigeraSecureEnterprise + enum: + - Calico + - TigeraSecureEnterprise + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: crds/operator.tigera.io_tigerastatuses_crd.yaml + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + name: tigerastatuses.operator.tigera.io +spec: + group: operator.tigera.io + names: + kind: TigeraStatus + listKind: TigeraStatusList + plural: tigerastatuses + singular: tigerastatus + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Whether the component running and stable. + jsonPath: .status.conditions[?(@.type=='Available')].status + name: Available + type: string + - description: Whether the component is processing changes. + jsonPath: .status.conditions[?(@.type=='Progressing')].status + name: Progressing + type: string + - description: Whether the component is degraded. + jsonPath: .status.conditions[?(@.type=='Degraded')].status + name: Degraded + type: string + - description: The time the component's Available status last changed. + jsonPath: .status.conditions[?(@.type=='Available')].lastTransitionTime + name: Since + type: date + name: v1 + schema: + openAPIV3Schema: + description: TigeraStatus represents the most recently observed status for + Calico or a Calico Enterprise functional area. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: TigeraStatusSpec defines the desired state of TigeraStatus + type: object + status: + description: TigeraStatusStatus defines the observed state of TigeraStatus + properties: + conditions: + description: Conditions represents the latest observed set of conditions + for this component. A component may be one or more of Available, + Progressing, or Degraded. + items: + description: TigeraStatusCondition represents a condition attached + to a particular component. + properties: + lastTransitionTime: + description: The timestamp representing the start time for the + current status. + format: date-time + type: string + message: + description: Optionally, a detailed message providing additional + context. + type: string + observedGeneration: + description: observedGeneration represents the generation that + the condition was set based upon. For instance, if generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + type: integer + reason: + description: A brief reason explaining the condition. + type: string + status: + description: The status of the condition. May be True, False, + or Unknown. + type: string + type: + description: The type of condition. May be Available, Progressing, + or Degraded. + type: string + required: + - lastTransitionTime + - status + - type + type: object + type: array + required: + - conditions + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +# Source: tigera-operator/templates/tigera-operator/02-serviceaccount-tigera-operator.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: tigera-operator + namespace: tigera-operator +--- +# Source: tigera-operator/templates/tigera-operator/02-role-tigera-operator.yaml +# Permissions required when running the operator for a Calico cluster. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: tigera-operator +rules: + - apiGroups: + - "" + resources: + - namespaces + - pods + - podtemplates + - services + - endpoints + - events + - configmaps + - secrets + - serviceaccounts + verbs: + - create + - get + - list + - update + - delete + - watch + - apiGroups: + - "" + resources: + - resourcequotas + verbs: + - list + - get + - watch + - apiGroups: + - "" + resources: + - resourcequotas + verbs: + - create + - get + - list + - update + - delete + - watch + resourceNames: + - calico-critical-pods + - tigera-critical-pods + - apiGroups: + - "" + resources: + - nodes + verbs: + # Need to update node labels when migrating nodes. + - get + - patch + - list + # We need this for Typha autoscaling + - watch + - apiGroups: + - rbac.authorization.k8s.io + resources: + - clusterroles + - clusterrolebindings + - rolebindings + - roles + verbs: + - create + - get + - list + - update + - delete + - watch + - bind + - escalate + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - statefulsets + verbs: + - create + - get + - list + - patch + - update + - delete + - watch + - apiGroups: + - apps + resourceNames: + - tigera-operator + resources: + - deployments/finalizers + verbs: + - update + - apiGroups: + - operator.tigera.io + resources: + - '*' + verbs: + - create + - get + - list + - update + - patch + - delete + - watch + - apiGroups: + - networking.k8s.io + resources: + - networkpolicies + verbs: + - create + - update + - delete + - get + - list + - watch + - apiGroups: + - crd.projectcalico.org + resources: + - felixconfigurations + verbs: + - create + - patch + - list + - get + - watch + - apiGroups: + - crd.projectcalico.org + resources: + - ippools + - kubecontrollersconfigurations + - bgpconfigurations + verbs: + - get + - list + - watch + - apiGroups: + - scheduling.k8s.io + resources: + - priorityclasses + verbs: + - create + - get + - list + - update + - delete + - watch + - apiGroups: + - policy + resources: + - poddisruptionbudgets + verbs: + - create + - get + - list + - update + - delete + - watch + - apiGroups: + - apiregistration.k8s.io + resources: + - apiservices + verbs: + - list + - watch + - create + - update + # Needed for operator lock + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - list + - update + - delete + - watch + # Add the appropriate pod security policy permissions + - apiGroups: + - policy + resources: + - podsecuritypolicies + resourceNames: + - tigera-operator + verbs: + - use + - apiGroups: + - policy + resources: + - podsecuritypolicies + verbs: + - get + - list + - watch + - create + - update + - delete +# Add the permissions to monitor the status of certificatesigningrequests when certificate management is enabled. + - apiGroups: + - certificates.k8s.io + resources: + - certificatesigningrequests + verbs: + - list + - watch + - apiGroups: + - storage.k8s.io + resources: + - csidrivers + verbs: + - list + - watch + - update + - get + - create + - delete +--- +# Source: tigera-operator/templates/tigera-operator/02-rolebinding-tigera-operator.yaml +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tigera-operator +subjects: +- kind: ServiceAccount + name: tigera-operator + namespace: tigera-operator +roleRef: + kind: ClusterRole + name: tigera-operator + apiGroup: rbac.authorization.k8s.io +--- +# Source: tigera-operator/templates/tigera-operator/02-tigera-operator.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tigera-operator + namespace: tigera-operator + labels: + k8s-app: tigera-operator +spec: + replicas: 1 + selector: + matchLabels: + name: tigera-operator + template: + metadata: + labels: + name: tigera-operator + k8s-app: tigera-operator + spec: + nodeSelector: + kubernetes.io/os: linux + tolerations: + - effect: NoExecute + operator: Exists + - effect: NoSchedule + operator: Exists + serviceAccountName: tigera-operator + hostNetwork: true + # This must be set when hostNetwork is true or else the cluster services won't resolve + dnsPolicy: ClusterFirstWithHostNet + containers: + - name: tigera-operator + image: quay.io/tigera/operator:v1.28.0 + imagePullPolicy: IfNotPresent + command: + - operator + volumeMounts: + - name: var-lib-calico + readOnly: true + mountPath: /var/lib/calico + env: + - name: WATCH_NAMESPACE + value: "" + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: OPERATOR_NAME + value: "tigera-operator" + - name: TIGERA_OPERATOR_INIT_IMAGE_VERSION + value: v1.28.0 + envFrom: + - configMapRef: + name: kubernetes-services-endpoint + optional: true + volumes: + - name: var-lib-calico + hostPath: + path: /var/lib/calico diff --git a/acceptance/framework/flags/flags.go b/acceptance/framework/flags/flags.go index ac11fc021d..81f8131efb 100644 --- a/acceptance/framework/flags/flags.go +++ b/acceptance/framework/flags/flags.go @@ -27,6 +27,8 @@ type TestFlags struct { flagEnablePodSecurityPolicies bool + flagEnableCNI bool + flagEnableTransparentProxy bool flagHelmChartVersion string @@ -40,6 +42,7 @@ type TestFlags struct { flagDebugDirectory string flagUseKind bool + flagUseGKE bool flagDisablePeering bool @@ -87,6 +90,10 @@ func (t *TestFlags) init() { flag.BoolVar(&t.flagEnablePodSecurityPolicies, "enable-pod-security-policies", false, "If true, the test suite will run tests with pod security policies enabled.") + flag.BoolVar(&t.flagEnableCNI, "enable-cni", false, + "If true, the test suite will run tests with consul-cni plugin enabled. "+ + "In general, this will only run against tests that are mesh related (connect, mesh-gateway, peering, etc") + flag.BoolVar(&t.flagEnableTransparentProxy, "enable-transparent-proxy", false, "If true, the test suite will run tests with transparent proxy enabled. "+ "This applies only to tests that enable connectInject.") @@ -100,6 +107,9 @@ func (t *TestFlags) init() { flag.BoolVar(&t.flagUseKind, "use-kind", false, "If true, the tests will assume they are running against a local kind cluster(s).") + flag.BoolVar(&t.flagUseGKE, "use-gke", false, + "If true, the tests will assume they are running against a GKE cluster(s).") + flag.BoolVar(&t.flagDisablePeering, "disable-peering", false, "If true, the peering tests will not run.") @@ -144,6 +154,8 @@ func (t *TestFlags) TestConfigFromFlags() *config.TestConfig { EnablePodSecurityPolicies: t.flagEnablePodSecurityPolicies, + EnableCNI: t.flagEnableCNI, + EnableTransparentProxy: t.flagEnableTransparentProxy, DisablePeering: t.flagDisablePeering, @@ -157,5 +169,6 @@ func (t *TestFlags) TestConfigFromFlags() *config.TestConfig { NoCleanupOnFailure: t.flagNoCleanupOnFailure, DebugDirectory: tempDir, UseKind: t.flagUseKind, + UseGKE: t.flagUseGKE, } } diff --git a/acceptance/tests/basic/basic_test.go b/acceptance/tests/basic/basic_test.go index c82368dcdd..0edab960d9 100644 --- a/acceptance/tests/basic/basic_test.go +++ b/acceptance/tests/basic/basic_test.go @@ -19,6 +19,10 @@ import ( // servers and clients, works by creating a kv entry // and subsequently reading it from Consul. func TestBasicInstallation(t *testing.T) { + cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and installing CNI is not a basic installation") + } cases := []struct { secure bool autoEncrypt bool diff --git a/acceptance/tests/consul-dns/consul_dns_test.go b/acceptance/tests/consul-dns/consul_dns_test.go index 126b97df81..e6973459cc 100644 --- a/acceptance/tests/consul-dns/consul_dns_test.go +++ b/acceptance/tests/consul-dns/consul_dns_test.go @@ -17,6 +17,10 @@ import ( const podName = "dns-pod" func TestConsulDNS(t *testing.T) { + cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set") + } for _, secure := range []bool{false, true} { name := fmt.Sprintf("secure: %t", secure) t.Run(name, func(t *testing.T) { diff --git a/acceptance/tests/controller/controller_namespaces_test.go b/acceptance/tests/controller/controller_namespaces_test.go index 3f757dc4df..51135556b1 100644 --- a/acceptance/tests/controller/controller_namespaces_test.go +++ b/acceptance/tests/controller/controller_namespaces_test.go @@ -33,6 +33,9 @@ const ( // and non-auto-encrypt secure installations, so testing just one is enough. func TestControllerNamespaces(t *testing.T) { cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and controller is already tested with regular tproxy") + } if !cfg.EnableEnterprise { t.Skipf("skipping this test because -enable-enterprise is not set") } diff --git a/acceptance/tests/controller/controller_test.go b/acceptance/tests/controller/controller_test.go index 6c8dcbe4e7..9451140aa0 100644 --- a/acceptance/tests/controller/controller_test.go +++ b/acceptance/tests/controller/controller_test.go @@ -28,7 +28,9 @@ const ( func TestController(t *testing.T) { cfg := suite.Config() - + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and controller is already tested with regular tproxy") + } cases := []struct { secure bool autoEncrypt bool diff --git a/acceptance/tests/partitions/partitions_sync_test.go b/acceptance/tests/partitions/partitions_sync_test.go index 49f265210e..59108b2d3a 100644 --- a/acceptance/tests/partitions/partitions_sync_test.go +++ b/acceptance/tests/partitions/partitions_sync_test.go @@ -24,6 +24,9 @@ func TestPartitions_Sync(t *testing.T) { env := suite.Environment() cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set") + } if !cfg.EnableEnterprise { t.Skipf("skipping this test because -enable-enterprise is not set") } diff --git a/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go b/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go index 4ef08dec6e..531e7a5274 100644 --- a/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go +++ b/acceptance/tests/snapshot-agent/snapshot_agent_k8s_secret_test.go @@ -28,6 +28,9 @@ import ( // a command line arg or an environment variable. func TestSnapshotAgent_K8sSecret(t *testing.T) { cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and snapshot agent is already tested with regular tproxy") + } ctx := suite.Environment().DefaultContext(t) kubectlOptions := ctx.KubectlOptions(t) ns := kubectlOptions.Namespace diff --git a/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go b/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go index a3ede3e984..a0f3539592 100644 --- a/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go +++ b/acceptance/tests/snapshot-agent/snapshot_agent_vault_test.go @@ -28,6 +28,9 @@ import ( // a command line arg or an environment variable. func TestSnapshotAgent_Vault(t *testing.T) { cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and snapshot agent is already tested with regular tproxy") + } ctx := suite.Environment().DefaultContext(t) kubectlOptions := ctx.KubectlOptions(t) ns := kubectlOptions.Namespace diff --git a/acceptance/tests/sync/sync_catalog_namespaces_test.go b/acceptance/tests/sync/sync_catalog_namespaces_test.go index c4fec80c98..79f592033c 100644 --- a/acceptance/tests/sync/sync_catalog_namespaces_test.go +++ b/acceptance/tests/sync/sync_catalog_namespaces_test.go @@ -25,6 +25,9 @@ const staticServerService = "static-server" // and non-auto-encrypt secure installations, so testing just one is enough. func TestSyncCatalogNamespaces(t *testing.T) { cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and sync catalog is already tested with regular tproxy") + } if !cfg.EnableEnterprise { t.Skipf("skipping this test because -enable-enterprise is not set") } diff --git a/acceptance/tests/sync/sync_catalog_test.go b/acceptance/tests/sync/sync_catalog_test.go index 94d02dbbba..942843d53f 100644 --- a/acceptance/tests/sync/sync_catalog_test.go +++ b/acceptance/tests/sync/sync_catalog_test.go @@ -18,6 +18,10 @@ import ( // The test will create a test service and a pod and will // wait for the service to be synced *to* consul. func TestSyncCatalog(t *testing.T) { + cfg := suite.Config() + if cfg.EnableCNI { + t.Skipf("skipping because -enable-cni is set and sync catalog is already tested with regular tproxy") + } cases := []struct { name string helmValues map[string]string diff --git a/charts/consul/templates/cni-clusterrole.yaml b/charts/consul/templates/cni-clusterrole.yaml new file mode 100644 index 0000000000..84551205c0 --- /dev/null +++ b/charts/consul/templates/cni-clusterrole.yaml @@ -0,0 +1,30 @@ +{{- if .Values.connectInject.cni.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +rules: +- apiGroups: [""] + resources: + - pods + verbs: + - get + - list + - watch + - patch + - update +- apiGroups: ["policy"] + resources: + - podsecuritypolicies + resourceNames: + - {{ template "consul.fullname" . }}-cni + verbs: + - use +{{- end }} diff --git a/charts/consul/templates/cni-clusterrolebinding.yaml b/charts/consul/templates/cni-clusterrolebinding.yaml new file mode 100644 index 0000000000..86c19d86aa --- /dev/null +++ b/charts/consul/templates/cni-clusterrolebinding.yaml @@ -0,0 +1,20 @@ +{{- if .Values.connectInject.cni.enabled }} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ template "consul.fullname" . }}-cni + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ template "consul.fullname" . }}-cni +subjects: +- kind: ServiceAccount + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/consul/templates/cni-daemonset.yaml b/charts/consul/templates/cni-daemonset.yaml new file mode 100644 index 0000000000..a74693da57 --- /dev/null +++ b/charts/consul/templates/cni-daemonset.yaml @@ -0,0 +1,83 @@ +{{- if (and (.Values.connectInject.cni.enabled) (not .Values.connectInject.enabled)) }}{{ fail "connectInject.enabled must be true if connectInject.cni.enabled is true" }}{{ end -}} +{{- if .Values.connectInject.cni.enabled }} +apiVersion: apps/v1 +kind: DaemonSet +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +spec: + {{- if .Values.connectInject.cni.updateStrategy }} + updateStrategy: + {{ tpl .Values.connectInject.cni.updateStrategy . | nindent 4 | trim }} + {{- end }} + selector: + matchLabels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + release: {{ .Release.Name }} + component: cni + template: + metadata: + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + release: {{ .Release.Name }} + component: cni + annotations: + consul.hashicorp.com/connect-inject: "false" + spec: + # consul-cni only runs on linux operating systems + nodeSelector: + kubernetes.io/os: linux + tolerations: + # Mark the pod as a critical add-on for rescheduling. + - key: CriticalAddonsOnly + operator: Exists + - effect: NoExecute + operator: Exists + # Tell kubernetes that this daemonset is critical so that it will be scheduled on a new node before other pods + priorityClassName: system-node-critical + serviceAccountName: {{ template "consul.fullname" . }}-cni + {{- if not .Values.global.openshift.enabled }} + securityContext: + {{- toYaml .Values.connectInject.cni.securityContext | nindent 8 -}} + {{- end }} + # Minimize downtime during a rolling upgrade or deletion; tell Kubernetes to do a "force + # deletion": https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods. + terminationGracePeriodSeconds: 10 + containers: + # This container installs the consul CNI binaries and CNI network config file on each node + - name: install-cni + image: {{ .Values.global.imageK8S }} + securityContext: + privileged: true + command: + - consul-k8s-control-plane + - install-cni + - -log-level={{ default .Values.global.logLevel .Values.connectInject.cni.logLevel }} + - -cni-bin-dir={{ .Values.connectInject.cni.cniBinDir }} + - -cni-net-dir={{ .Values.connectInject.cni.cniNetDir }} + {{- with .Values.connectInject.cni.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - mountPath: {{ .Values.connectInject.cni.cniBinDir }} + name: cni-bin-dir + - mountPath: {{ .Values.connectInject.cni.cniNetDir }} + name: cni-net-dir + volumes: + # Used to install CNI. + - name: cni-bin-dir + hostPath: + path: {{ .Values.connectInject.cni.cniBinDir }} + - name: cni-net-dir + hostPath: + path: {{ .Values.connectInject.cni.cniNetDir }} +{{- end }} diff --git a/charts/consul/templates/cni-podsecuritypolicy.yaml b/charts/consul/templates/cni-podsecuritypolicy.yaml new file mode 100644 index 0000000000..15b96bc230 --- /dev/null +++ b/charts/consul/templates/cni-podsecuritypolicy.yaml @@ -0,0 +1,31 @@ +{{- if (and .Values.connectInject.cni.enabled .Values.global.enablePodSecurityPolicies) }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +spec: + privileged: true + # GKE requires that allowPrivilegeEscalation:true if privileged: true. + allowPrivilegeEscalation: true + volumes: + - hostPath + - secret + - emptyDir + hostNetwork: false + readOnlyRootFilesystem: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' +{{- end }} diff --git a/charts/consul/templates/cni-resourcequota.yaml b/charts/consul/templates/cni-resourcequota.yaml new file mode 100644 index 0000000000..abfe5a8876 --- /dev/null +++ b/charts/consul/templates/cni-resourcequota.yaml @@ -0,0 +1,22 @@ +{{- if .Values.connectInject.cni.enabled }} +apiVersion: v1 +kind: ResourceQuota +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +spec: + hard: + pods: {{ .Values.connectInject.cni.resourceQuota.pods | quote }} + scopeSelector: + matchExpressions: + - operator: In + scopeName: PriorityClass + values: + - system-node-critical +{{- end }} diff --git a/charts/consul/templates/cni-serviceaccount.yaml b/charts/consul/templates/cni-serviceaccount.yaml new file mode 100644 index 0000000000..6b2a7627f7 --- /dev/null +++ b/charts/consul/templates/cni-serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- if .Values.connectInject.cni.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +{{- with .Values.global.imagePullSecrets }} +imagePullSecrets: +{{- range . }} +- name: {{ .name }} +{{- end }} +{{- end }} +{{- end}} diff --git a/charts/consul/templates/connect-inject-clusterrole.yaml b/charts/consul/templates/connect-inject-clusterrole.yaml index 846e70132a..afb485c227 100644 --- a/charts/consul/templates/connect-inject-clusterrole.yaml +++ b/charts/consul/templates/connect-inject-clusterrole.yaml @@ -19,11 +19,19 @@ rules: - get {{- end }} - apiGroups: [ "" ] - resources: [ "pods", "endpoints", "services", "namespaces", "nodes" ] + resources: [ "endpoints", "services", "namespaces", "nodes" ] verbs: - "get" - "list" - "watch" +- apiGroups: [ "" ] + resources: + - pods + verbs: + - "get" + - "list" + - "watch" + - "update" - apiGroups: - coordination.k8s.io resources: diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index a5cae8edc5..779dceb572 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -139,6 +139,7 @@ spec: {{- else }} -default-enable-transparent-proxy=false \ {{- end }} + -enable-cni={{ .Values.connectInject.cni.enabled }} \ {{- if .Values.global.peering.enabled }} -enable-peering=true \ {{- if (eq .Values.global.peering.tokenGeneration.serverAddresses.source "") }} diff --git a/charts/consul/test/unit/cni-clusterrole.bats b/charts/consul/test/unit/cni-clusterrole.bats new file mode 100644 index 0000000000..02675ed882 --- /dev/null +++ b/charts/consul/test/unit/cni-clusterrole.bats @@ -0,0 +1,31 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/ClusterRole: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-clusterrole.yaml \ + . +} + +@test "cni/ClusterRole: enabled with connectInject.cni.enabled=true and connectInject.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-clusterrole.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [[ "${actual}" == "true" ]] +} + +@test "cni/ClusterRole: disabled with connectInject.cni.enabled=false and connectInject.enabled=true" { + cd `chart_dir` + assert_empty helm template \ + --set 'connectInject.cni.enabled=false' \ + --set 'connectInject.enabled=true' \ + -s templates/cni-clusterrole.yaml \ + . +} + diff --git a/charts/consul/test/unit/cni-clusterrolebinding.bats b/charts/consul/test/unit/cni-clusterrolebinding.bats new file mode 100644 index 0000000000..ba217e7706 --- /dev/null +++ b/charts/consul/test/unit/cni-clusterrolebinding.bats @@ -0,0 +1,57 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/ClusterRoleBinding: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-clusterrolebinding.yaml \ + . +} + +@test "cni/ClusterRoleBinding: enabled with connectInject.cni.enabled=true and connectInject.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-clusterrolebinding.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [[ "${actual}" == "true" ]] +} + +@test "cni/ClusterRoleBinding: disabled with connectInject.cni.enabled=false and connectInject.enabled=true" { + cd `chart_dir` + assert_empty helm template \ + --set 'connectInject.cni.enabled=false' \ + --set 'connectInject.enabled=true' \ + -s templates/cni-clusterrolebinding.yaml \ + . +} + +#-------------------------------------------------------------------- +# subjects + +@test "cni/ClusterRoleBinding: subject name is correct" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-clusterrolebinding.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.subjects[0].name' | tee /dev/stderr) + [ "${actual}" = "release-name-consul-cni" ] +} + +@test "cni/ClusterRoleBinding: subject namespace is correct" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-clusterrolebinding.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --namespace foo \ + . | tee /dev/stderr | + yq -r '.subjects[0].namespace' | tee /dev/stderr) + [ "${actual}" = "foo" ] +} + diff --git a/charts/consul/test/unit/cni-daemonset.bats b/charts/consul/test/unit/cni-daemonset.bats new file mode 100644 index 0000000000..e826642a00 --- /dev/null +++ b/charts/consul/test/unit/cni-daemonset.bats @@ -0,0 +1,293 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/DaemonSet: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-daemonset.yaml \ + . +} + +@test "cni/DaemonSet: enabled with connectInject.cni.enabled=true and connectInject.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [[ "${actual}" == "true" ]] +} + +@test "cni/DaemonSet: disabled with connectInject.cni.enabled=false and connectInject.enabled=true" { + cd `chart_dir` + assert_empty helm template \ + --set 'connectInject.cni.enabled=false' \ + --set 'connectInject.enabled=true' \ + -s templates/cni-daemonset.yaml \ + . +} + +@test "cni/DaemonSet: throws error when connectInject.enabled=true and connectInject.enabled=false" { + cd `chart_dir` + run helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=false' \ + -s templates/cni-daemonset.yaml \ + . + + [ "$status" -eq 1 ] + [[ "$output" =~ "connectInject.enabled must be true if connectInject.cni.enabled is true" ]] +} + +@test "cni/DaemonSet: image defaults to global.imageK8S" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.imageK8S=foo' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].image' | tee /dev/stderr) + [ "${actual}" = "foo" ] +} + +@test "cni/Daemonset: all command arguments" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.logLevel=bar' \ + --set 'connectInject.cni.cniBinDir=baz' \ + --set 'connectInject.cni.cniNetDir=foo' \ + bar \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("consul-k8s-control-plane"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo "$cmd" | + yq 'any(contains("install-cni"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo "$cmd" | + yq 'any(contains("log-level=bar"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo "$cmd" | + yq 'any(contains("cni-bin-dir=baz"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo "$cmd" | + yq 'any(contains("cni-net-dir=foo"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +#-------------------------------------------------------------------- +# updateStrategy + +@test "cni/DaemonSet: no updateStrategy by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.updateStrategy' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "cni/DaemonSet: updateStrategy can be set" { + cd `chart_dir` + local updateStrategy="type: RollingUpdate +rollingUpdate: + maxUnavailable: 5 +" + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set "connectInject.cni.updateStrategy=${updateStrategy}" \ + . | tee /dev/stderr | \ + yq -c '.spec.updateStrategy == {"type":"RollingUpdate","rollingUpdate":{"maxUnavailable":5}}' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + + +#-------------------------------------------------------------------- +# resources + +@test "cni/DaemonSet: resources defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -rc '.spec.template.spec.containers[0].resources' | tee /dev/stderr) + [ "${actual}" = '{"limits":{"cpu":"100m","memory":"100Mi"},"requests":{"cpu":"75m","memory":"75Mi"}}' ] +} + +@test "cni/DaemonSet: resources can be overridden" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.resources.foo=bar' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].resources.foo' | tee /dev/stderr) + [ "${actual}" = "bar" ] +} + +#-------------------------------------------------------------------- +# securityContext + +@test "cni/DaemonSet: securityContext is not set when global.openshift.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.openshift.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.securityContext' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "cni/DaemonSet: sets default security context settings" { + cd `chart_dir` + local security_context=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.securityContext' | tee /dev/stderr) + + local actual=$(echo $security_context | jq -r .runAsNonRoot) + [ "${actual}" = "false" ] + + local actual=$(echo $security_context | jq -r .runAsUser) + [ "${actual}" = "0" ] + + local actual=$(echo $security_context | jq -r .runAsGroup) + [ "${actual}" = "0" ] +} + +@test "cni/DaemonSet: can overwrite security context settings" { + cd `chart_dir` + local security_context=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.securityContext.runAsNonRoot=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.securityContext' | tee /dev/stderr) + + local actual=$(echo $security_context | jq -r .runAsNonRoot) + [ "${actual}" = "true" ] +} + +#-------------------------------------------------------------------- +# volumes + +@test "cni/DaemonSet: sets default cni-bin-dir volume hostPath" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.volumes[] | select(.name == "cni-bin-dir")' | tee /dev/stderr) + [ "${actual}" = '{"name":"cni-bin-dir","hostPath":{"path":"/opt/cni/bin"}}' ] +} + +@test "cni/DaemonSet: sets default cni-net-dir volume hostPath" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.volumes[] | select(.name == "cni-net-dir")' | tee /dev/stderr) + [ "${actual}" = '{"name":"cni-net-dir","hostPath":{"path":"/etc/cni/net.d"}}' ] +} + +@test "cni/DaemonSet: can overwrite default cni-bin-dir volume hostPath" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.cniBinDir=foo' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.volumes[] | select(.name == "cni-bin-dir")' | tee /dev/stderr) + [ "${actual}" = '{"name":"cni-bin-dir","hostPath":{"path":"foo"}}' ] +} + +@test "cni/DaemonSet: can overwrite cni-net-dir volume hostPath" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.cniNetDir=bar' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.volumes[] | select(.name == "cni-net-dir")' | tee /dev/stderr) + [ "${actual}" = '{"name":"cni-net-dir","hostPath":{"path":"bar"}}' ] +} + +#-------------------------------------------------------------------- +# volumeMounts + +@test "cni/DaemonSet: sets default host cni-bin-dir volumeMount" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.containers[0].volumeMounts[] | select(.name == "cni-bin-dir")' | tee /dev/stderr) + [ "${actual}" = '{"mountPath":"/opt/cni/bin","name":"cni-bin-dir"}' ] +} + +@test "cni/DaemonSet: sets default host cni-net-dir volumeMount" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.containers[0].volumeMounts[] | select(.name == "cni-net-dir")' | tee /dev/stderr) + [ "${actual}" = '{"mountPath":"/etc/cni/net.d","name":"cni-net-dir"}' ] +} + +@test "cni/DaemonSet: can overwrite host cni-bin-dir volumeMount" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.cniBinDir=foo' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.containers[0].volumeMounts[] | select(.name == "cni-bin-dir")' | tee /dev/stderr) + [ "${actual}" = '{"mountPath":"foo","name":"cni-bin-dir"}' ] +} + +@test "cni/DaemonSet: can overwrite host cni-net-dir volumeMount" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.cniNetDir=bar' \ + . | tee /dev/stderr | + yq -r -c '.spec.template.spec.containers[0].volumeMounts[] | select(.name == "cni-net-dir")' | tee /dev/stderr) + [ "${actual}" = '{"mountPath":"bar","name":"cni-net-dir"}' ] +} + diff --git a/charts/consul/test/unit/cni-podsecuritypolicy.bats b/charts/consul/test/unit/cni-podsecuritypolicy.bats new file mode 100644 index 0000000000..37df761995 --- /dev/null +++ b/charts/consul/test/unit/cni-podsecuritypolicy.bats @@ -0,0 +1,32 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/PodSecurityPolicy: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-podsecuritypolicies.yaml \ + . +} + +@test "cni/PodSecurityPolicy: disabled with cni disabled and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-podsecuritypolicy.yaml \ + --set 'connectInject.cni.enabled=false' \ + --set 'global.enablePodSecurityPolicies=true' \ + . +} + +@test "cni/PodSecurityPolicy: enabled with connectInject.cni.enabled=true and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-podsecuritypolicy.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.enablePodSecurityPolicies=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [[ "${actual}" == "true" ]] +} + diff --git a/charts/consul/test/unit/cni-resourcequota.bats b/charts/consul/test/unit/cni-resourcequota.bats new file mode 100644 index 0000000000..36c7a26b30 --- /dev/null +++ b/charts/consul/test/unit/cni-resourcequota.bats @@ -0,0 +1,57 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/ResourceQuota: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-resourcequota.yaml \ + . +} + +@test "cni/ResourceQuota: enabled with connectInject.cni.enabled=true and connectInject.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-resourcequota.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [[ "${actual}" == "true" ]] +} + +@test "cni/ResourceQuota: disabled with connectInject.cni.enabled=false and connectInject.enabled=true" { + cd `chart_dir` + assert_empty helm template \ + --set 'connectInject.cni.enabled=false' \ + --set 'connectInject.enabled=true' \ + -s templates/cni-resourcequota.yaml \ + . +} + +#-------------------------------------------------------------------- +# pods + +@test "cni/ResourceQuota: resources defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-resourcequota.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -rc '.spec.hard.pods' | tee /dev/stderr) + [ "${actual}" = "5000" ] +} + +@test "cni/ResourceQuota: resources can be overridden" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-resourcequota.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.resourceQuota.pods=bar' \ + . | tee /dev/stderr | + yq -rc '.spec.hard.pods' | tee /dev/stderr) + [ "${actual}" = "bar" ] +} + diff --git a/charts/consul/test/unit/cni-serviceaccount.bats b/charts/consul/test/unit/cni-serviceaccount.bats new file mode 100644 index 0000000000..4f2071f823 --- /dev/null +++ b/charts/consul/test/unit/cni-serviceaccount.bats @@ -0,0 +1,53 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/ServiceAccount: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-serviceaccount.yaml \ + . +} + +@test "cni/ServiceAccount: enabled with connectInject.cni.enabled=true and connectInject.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-serviceaccount.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [[ "${actual}" == "true" ]] +} + +@test "cni/ServiceAccount: disabled with connectInject.cni.enabled=false and connectInject.enabled=true" { + cd `chart_dir` + assert_empty helm template \ + --set 'connectInject.cni.enabled=false' \ + --set 'connectInject.enabled=true' \ + -s templates/cni-serviceaccount.yaml \ + . +} + +#-------------------------------------------------------------------- +# global.imagePullSecrets + +@test "cni/ServiceAccount: can set image pull secrets" { + cd `chart_dir` + local object=$(helm template \ + -s templates/cni-serviceaccount.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.imagePullSecrets[0].name=my-secret' \ + --set 'global.imagePullSecrets[1].name=my-secret2' \ + . | tee /dev/stderr) + + local actual=$(echo "$object" | + yq -r '.imagePullSecrets[0].name' | tee /dev/stderr) + [ "${actual}" = "my-secret" ] + + local actual=$(echo "$object" | + yq -r '.imagePullSecrets[1].name' | tee /dev/stderr) + [ "${actual}" = "my-secret2" ] +} + diff --git a/charts/consul/test/unit/connect-inject-clusterrole.bats b/charts/consul/test/unit/connect-inject-clusterrole.bats index 7939755f81..39687badef 100644 --- a/charts/consul/test/unit/connect-inject-clusterrole.bats +++ b/charts/consul/test/unit/connect-inject-clusterrole.bats @@ -32,7 +32,7 @@ load _helpers #-------------------------------------------------------------------- # rules -@test "connectInject/ClusterRole: sets get, list, and watch access to pods, endpoints, services, and namespaces in all api groups" { +@test "connectInject/ClusterRole: sets get, list, and watch access to endpoints, services, namespaces and nodes in all api groups" { cd `chart_dir` local object=$(helm template \ -s templates/connect-inject-clusterrole.yaml \ @@ -42,9 +42,6 @@ load _helpers . | tee /dev/stderr | yq -r '.rules[0]' | tee /dev/stderr) - local actual=$(echo $object | yq -r '.resources[| index("pods")' | tee /dev/stderr) - [ "${actual}" != null ] - local actual=$(echo $object | yq -r '.resources[| index("endpoints")' | tee /dev/stderr) [ "${actual}" != null ] @@ -54,6 +51,9 @@ load _helpers local actual=$(echo $object | yq -r '.resources[| index("namespaces")' | tee /dev/stderr) [ "${actual}" != null ] + local actual=$(echo $object | yq -r '.resources[| index("nodes")' | tee /dev/stderr) + [ "${actual}" != null ] + local actual=$(echo $object | yq -r '.apiGroups[0]' | tee /dev/stderr) [ "${actual}" = "" ] @@ -67,7 +67,7 @@ load _helpers [ "${actual}" != null ] } -@test "connectInject/ClusterRole: sets create, get, list, and update access to leases in the coordination.k8s.io api group" { +@test "connectInject/ClusterRole: sets get, list, watch and update access to pods in all api groups" { cd `chart_dir` local object=$(helm template \ -s templates/connect-inject-clusterrole.yaml \ @@ -77,6 +77,35 @@ load _helpers . | tee /dev/stderr | yq -r '.rules[1]' | tee /dev/stderr) + local actual=$(echo $object | yq -r '.resources[| index("pods")' | tee /dev/stderr) + [ "${actual}" != null ] + + local actual=$(echo $object | yq -r '.apiGroups[0]' | tee /dev/stderr) + [ "${actual}" = "" ] + + local actual=$(echo $object | yq -r '.verbs | index("get")' | tee /dev/stderr) + [ "${actual}" != null ] + + local actual=$(echo $object | yq -r '.verbs | index("list")' | tee /dev/stderr) + [ "${actual}" != null ] + + local actual=$(echo $object | yq -r '.verbs | index("watch")' | tee /dev/stderr) + [ "${actual}" != null ] + + local actual=$(echo $object | yq -r '.verbs | index("update")' | tee /dev/stderr) + [ "${actual}" != null ] +} + +@test "connectInject/ClusterRole: sets create, get, list, and update access to leases in the coordination.k8s.io api group" { + cd `chart_dir` + local object=$(helm template \ + -s templates/connect-inject-clusterrole.yaml \ + --set 'global.enabled=false' \ + --set 'client.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.rules[2]' | tee /dev/stderr) + local actual=$(echo $object | yq -r '.resources[| index("leases")' | tee /dev/stderr) [ "${actual}" != null ] @@ -166,7 +195,7 @@ load _helpers --set 'global.secretsBackend.vault.consulServerRole=bar' \ --set 'global.secretsBackend.vault.consulCARole=test2' \ . | tee /dev/stderr | - yq -r '.rules[2]' | tee /dev/stderr) + yq -r '.rules[3]' | tee /dev/stderr) local actual=$(echo $object | yq -r '.resources[0]' | tee /dev/stderr) [ "${actual}" = "mutatingwebhookconfigurations" ] diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 22464ae1b4..8ab6c3855f 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1795,6 +1795,36 @@ EOF [ "${actual}" = "true" ] } +#-------------------------------------------------------------------- +# cni + +@test "connectInject/Deployment: cni is disabled by default" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("-enable-cni=false"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "connectInject/Deployment: cni can be enabled by setting connectInject.cni.enabled=true" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq 'any(contains("-enable-cni=true"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # peering diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 84b50a6400..7f00ef6ef2 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -551,8 +551,7 @@ global: # `-consul-federation`. createFederationSecret: false - # The name of the primary datacenter. This should only be set for datacenters - # that are not the primary datacenter. + # The name of the primary datacenter. # @type: string primaryDatacenter: null @@ -1933,6 +1932,74 @@ connectInject: # @type: integer maxUnavailable: null + # Configures consul-cni plugin for Consul Service mesh services + cni: + # If true, then all traffic redirection setup will use the consul-cni plugin. + # Requires connectInject.enabled to also be true. + # @type: boolean + enabled: false + + # Log level for the installer and plugin. Overrides global.logLevel + # @type: string + logLevel: null + + # Location on the kubernetes node where the CNI plugin is installed. Shoud be the absolute path and start with a '/' + # Example on GKE: + # + # ```yaml + # cniBinDir: "/home/kubernetes/bin" + # ``` + # @type: string + cniBinDir: "/opt/cni/bin" + + # Location on the kubernetes node of all CNI configuration. Should be the absolute path and start with a '/' + # @type: string + cniNetDir: "/etc/cni/net.d" + + # The resource settings for CNI installer daemonset. + # @recurse: false + # @type: map + resources: + requests: + memory: "75Mi" + cpu: "75m" + limits: + memory: "100Mi" + cpu: "100m" + + # Resource quotas for running the daemonset as system critical pods + resourceQuota: + pods: 5000 + + # The security context for the CNI installer daemonset. This should be a YAML map corresponding to a + # Kubernetes [SecurityContext](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/) object. + # By default, servers will run as root, with user ID `0` and group ID `0`. + # Note: if running on OpenShift, this setting is ignored because the user and group are set automatically + # by the OpenShift platform. + # @type: map + # @recurse: false + securityContext: + runAsNonRoot: false + runAsGroup: 0 + runAsUser: 0 + + # updateStrategy for the CNI installer DaemonSet. + # See https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#daemonset-update-strategy. + # This should be a multi-line string mapping directly to the updateStrategy + # + # Example: + # + # ```yaml + # updateStrategy: | + # rollingUpdate: + # maxUnavailable: 5 + # type: RollingUpdate + # ``` + # + # @type: string + updateStrategy: null + + # Configures metrics for Consul Connect services. All values are overridable # via annotations on a per-pod basis. metrics: diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 73926fdf69..459b5f974d 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -20,6 +20,7 @@ FROM alpine:3.16 AS dev # NAME and VERSION are the name of the software in releases.hashicorp.com # and the version to download. Example: NAME=consul VERSION=1.2.3. ARG BIN_NAME=consul-k8s-control-plane +ARG CNI_BIN_NAME=consul-cni ARG VERSION ARG TARGETARCH ARG TARGETOS @@ -43,6 +44,7 @@ RUN addgroup ${BIN_NAME} && \ adduser -S -G ${BIN_NAME} 100 COPY pkg/bin/linux_${TARGETARCH}/${BIN_NAME} /bin +COPY cni/pkg/bin/linux_${TARGETARCH}/${CNI_BIN_NAME} /bin USER 100 CMD /bin/${BIN_NAME} @@ -67,6 +69,7 @@ CMD /bin/${BIN_NAME} FROM alpine:3.16 AS release-default ARG BIN_NAME=consul-k8s-control-plane +ARG CNI_BIN_NAME=consul-cni ARG PRODUCT_VERSION LABEL name=${BIN_NAME} \ @@ -90,7 +93,9 @@ ARG TARGETARCH # Create a non-root user to run the software. RUN addgroup ${BIN_NAME} && \ adduser -S -G ${BIN_NAME} 100 + COPY dist/${TARGETOS}/${TARGETARCH}/${BIN_NAME} /bin/ +COPY cni/dist/${TARGETOS}/${TARGETARCH}/${CNI_BIN_NAME} /bin/ USER 100 CMD /bin/${BIN_NAME} @@ -112,6 +117,8 @@ ARG PRODUCT_NAME ARG PRODUCT_VERSION ARG PRODUCT_REVISION ARG BIN_NAME +ARG CNI_BIN_NAME=consul-cni +ARG VERSION # PRODUCT_NAME and PRODUCT_VERSION are the name of the software on releases.hashicorp.com # and the version to download. Example: PRODUCT_NAME=consul PRODUCT_VERSION=1.2.3. @@ -149,6 +156,7 @@ RUN groupadd --gid 1000 ${BIN_NAME} && \ usermod -a -G root ${BIN_NAME} COPY dist/${TARGETOS}/${TARGETARCH}/${BIN_NAME} /bin/ +COPY cni/dist/${TARGETOS}/${TARGETARCH}/${CNI_BIN_NAME} /bin/ USER 100 CMD /bin/${BIN_NAME} diff --git a/control-plane/build-support/functions/20-build.sh b/control-plane/build-support/functions/20-build.sh index dd1551589f..ddde7b6acf 100644 --- a/control-plane/build-support/functions/20-build.sh +++ b/control-plane/build-support/functions/20-build.sh @@ -233,7 +233,7 @@ function build_consul_local { is_set "${NOGOX}" && use_gox=0 which gox > /dev/null || use_gox=0 - status_stage "==> Building Consul - OSes: ${build_os}, Architectures: ${build_arch}" + status_stage "==> Building ${bin_name} - OSes: ${build_os}, Architectures: ${build_arch}" mkdir pkg.bin.new 2> /dev/null if is_set "${use_gox}" then @@ -255,14 +255,14 @@ function build_consul_local { return 1 fi else - status "Building sequentially with go install" + status "Building sequentially with go build" for os in ${build_os} do for arch in ${build_arch} do outdir="pkg.bin.new/${extra_dir}${os}_${arch}" osarch="${os}/${arch}" - if test "${osarch}" == "darwin/arm" -o "${osarch}" == "darwin/arm64" -o "${osarch}" == "freebsd/arm64" -o "${osarch}" == "windows/arm" -o "${osarch}" == "windows/arm64" + if test "${osarch}" == "darwin/arm" -o "${osarch}" == "freebsd/arm64" -o "${osarch}" == "windows/arm" -o "${osarch}" == "windows/arm64" then continue fi @@ -287,7 +287,7 @@ function build_consul_local { else OS_BIN_EXTENSION="" fi - CGO_ENABLED=0 GOOS=${os} GOARCH=${arch} go install -ldflags "${GOLDFLAGS}" -tags "${GOTAGS}" && cp "${MAIN_GOPATH}/bin/${GOBIN_EXTRA}"/control-plane${OS_BIN_EXTENSION} "${outdir}/${bin_name}" + CGO_ENABLED=0 GOOS=${os} GOARCH=${arch} go build -ldflags "${GOLDFLAGS}" -tags "${GOTAGS}" -o "${outdir}/${bin_name}" if test $? -ne 0 then err "ERROR: Failed to build Consul for ${osarch}" diff --git a/control-plane/build-support/scripts/build-local.sh b/control-plane/build-support/scripts/build-local.sh index 9239271423..95d18e0ba6 100755 --- a/control-plane/build-support/scripts/build-local.sh +++ b/control-plane/build-support/scripts/build-local.sh @@ -99,6 +99,7 @@ function main { done build_consul_local "${sdir}" "${build_os}" "${build_arch}" "consul-k8s-control-plane" || return 1 + build_consul_local "${sdir}/cni" "${build_os}" "${build_arch}" "consul-cni" || return 1 return 0 } diff --git a/control-plane/cni/config/config.go b/control-plane/cni/config/config.go new file mode 100644 index 0000000000..f22d3ff79b --- /dev/null +++ b/control-plane/cni/config/config.go @@ -0,0 +1,42 @@ +package config + +const ( + DefaultPluginName = "consul-cni" + DefaultPluginType = "consul-cni" + DefaultCNIBinDir = "/opt/cni/bin" + DefaultCNINetDir = "/etc/cni/net.d" + DefaultMultus = false + // defaultKubeconfig is named ZZZ-.. as part of a convention that other CNI plugins use. + DefaultKubeconfig = "ZZZ-consul-cni-kubeconfig" + DefaultLogLevel = "info" +) + +// CNIConfig is the configuration that both the CNI installer and plugin will use. +type CNIConfig struct { + // Name of the plugin. + Name string `json:"name" mapstructure:"name"` + // Type of plugin (consul-cni). + Type string `json:"type" mapstructure:"type"` + // CNIBinDir is the location of the cni config files on the node. Can bet as a cli flag. + CNIBinDir string `json:"cni_bin_dir" mapstructure:"cni_bin_dir"` + // CNINetDir is the locaion of the cni plugin on the node. Can be set as a cli flag. + CNINetDir string `json:"cni_net_dir" mapstructure:"cni_net_dir"` + // Kubeconfig file name. Can be set as a cli flag. + Kubeconfig string `json:"kubeconfig" mapstructure:"kubeconfig"` + // LogLevl is the logging level. Can be set as a cli flag. + LogLevel string `json:"log_level" mapstructure:"log_level"` + // Multus is if the plugin is a multus plugin. Can be set as a cli flag. + Multus bool `json:"multus" mapstructure:"multus"` +} + +func NewDefaultCNIConfig() *CNIConfig { + return &CNIConfig{ + Name: DefaultPluginName, + Type: DefaultPluginType, + CNIBinDir: DefaultCNIBinDir, + CNINetDir: DefaultCNINetDir, + Kubeconfig: DefaultKubeconfig, + LogLevel: DefaultLogLevel, + Multus: DefaultMultus, + } +} diff --git a/control-plane/cni/go.mod b/control-plane/cni/go.mod new file mode 100644 index 0000000000..660b720d43 --- /dev/null +++ b/control-plane/cni/go.mod @@ -0,0 +1,55 @@ +module github.com/hashicorp/consul-k8s/control-plane/cni + +require ( + github.com/cenkalti/backoff v2.1.1+incompatible + github.com/containernetworking/cni v1.1.1 + github.com/containernetworking/plugins v1.1.1 + github.com/hashicorp/consul/sdk v0.9.0 + github.com/hashicorp/go-hclog v0.16.1 + github.com/stretchr/testify v1.7.1 + k8s.io/api v0.22.2 + k8s.io/apimachinery v0.22.2 + k8s.io/client-go v0.22.2 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect + github.com/fatih/color v1.12.0 // indirect + github.com/go-logr/logr v0.4.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/google/go-cmp v0.5.7 // indirect + github.com/google/gofuzz v1.1.0 // indirect + github.com/googleapis/gnostic v0.5.5 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/json-iterator/go v1.1.11 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-isatty v0.0.13 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.1.0 // indirect + golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/protobuf v1.26.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + k8s.io/klog/v2 v2.9.0 // indirect + k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect + k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + sigs.k8s.io/yaml v1.2.0 // indirect +) + +replace github.com/hashicorp/consul/sdk v0.9.0 => github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50 + +go 1.18 diff --git a/control-plane/cni/go.sum b/control-plane/cni/go.sum new file mode 100644 index 0000000000..03309565a1 --- /dev/null +++ b/control-plane/cni/go.sum @@ -0,0 +1,500 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= +github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/containernetworking/cni v1.1.1 h1:ky20T7c0MvKvbMOwS/FrlbNwjEoqJEUUYfsL4b0mc4k= +github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNGz0C1d3wVYlHE= +github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +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= +github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= +github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= +github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50 h1:GwbRRT+QxMRbYI608FGwTfcZ0iOVLX69B2ePjpQoyXw= +github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o= +github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= +github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= +k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= +k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= +k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= +k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= +k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= +k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= +k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/control-plane/cni/main.go b/control-plane/cni/main.go new file mode 100644 index 0000000000..c0685efb52 --- /dev/null +++ b/control-plane/cni/main.go @@ -0,0 +1,277 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "net" + "path/filepath" + + "github.com/containernetworking/cni/pkg/skel" + "github.com/containernetworking/cni/pkg/types" + current "github.com/containernetworking/cni/pkg/types/100" + "github.com/containernetworking/cni/pkg/version" + "github.com/hashicorp/consul/sdk/iptables" + "github.com/hashicorp/go-hclog" + corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + bv "github.com/containernetworking/plugins/pkg/utils/buildversion" +) + +const ( + // These annotations are duplicated from control-plane/connect-inject/annotations.go in + // order to prevent pulling in dependencies. + + // keyInjectStatus is the key of the annotation that is added to + // a pod after an injection is done. + keyInjectStatus = "consul.hashicorp.com/connect-inject-status" + + // keyTransparentProxyStatus is the key of the annotation that is added to + // a pod when transparent proxy is done. + keyTransparentProxyStatus = "consul.hashicorp.com/transparent-proxy-status" + + // waiting is used in conjunction with keyTransparentProxyStatus as a simple way to + // indicate the status of the CNI plugin. + waiting = "waiting" + + // complete is used in conjunction with keyTransparentProxyStatus as a simple way to + // indicate the status of the CNI plugin. + complete = "complete" + + // annotationRedirectTraffic stores iptables.Config information so that the CNI plugin can use it to apply + // iptables rules. + annotationRedirectTraffic = "consul.hashicorp.com/redirect-traffic-config" +) + +type Command struct { + // client is a kubernetes client + client kubernetes.Interface + // iptablesProvider is the Provider that will apply iptables rules. Used for testing. + iptablesProvider iptables.Provider +} + +type CNIArgs struct { + // types.CommonArgs are args that are passed as part of the CNI standard. + types.CommonArgs + // IP address assigned to the pod from a previous plugin. + IP net.IP + // K8S_POD_NAME is the pod that the plugin is running for. + K8S_POD_NAME types.UnmarshallableString + // K8S_POD_NAMESPACE is the namespace that the plugin is running for. + K8S_POD_NAMESPACE types.UnmarshallableString + // K8S_POD_INFRA_CONTAINER_ID is the runtime container ID that the pod runs under. + K8S_POD_INFRA_CONTAINER_ID types.UnmarshallableString +} + +// PluginConf is is the configuration used by the plugin. +type PluginConf struct { + // NetConf is the CNI Specification configuration for standard fields like Name, Type, + // CNIVersion and PrevResult. + types.NetConf + + // RuntimeConfig is the config passed from the kubelet to plugin at runtime. + RuntimeConfig *struct{} `json:"runtime_config"` + + // Name of the plugin (consul-cni). + Name string `json:"name"` + // Type of plugin (consul-cni). + Type string `json:"type"` + // CNIBinDir is the location of the cni config files on the node. Can be set as a cli flag. + CNIBinDir string `json:"cni_bin_dir"` + // CNINetDir is the location of the cni plugin on the node. Can be set as a cli flag. + CNINetDir string `json:"cni_net_dir"` + // Multus is if the plugin is a multus plugin. Can be set as a cli flag. + Multus bool `json:"multus"` + // Kubeconfig file name. Can be set as a cli flag. + Kubeconfig string `json:"kubeconfig"` + // LogLevl is the logging level. Can be set as a cli flag. + LogLevel string `json:"log_level"` + // +} + +// parseConfig parses the supplied CNI configuration (and prevResult) from stdin. +func parseConfig(stdin []byte) (*PluginConf, error) { + cfg := PluginConf{} + + if err := json.Unmarshal(stdin, &cfg); err != nil { + return nil, fmt.Errorf("failed to parse network configuration: %w", err) + } + + // The previous result is passed from the previously run plugin to our plugin. We do not + // do anything with the result but instead just pass it on when our plugin is finished. + if err := version.ParsePrevResult(&cfg.NetConf); err != nil { + return nil, fmt.Errorf("could not parse prevResult: %w", err) + } + + return &cfg, nil +} + +// cmdAdd is called for ADD requests. +func (c *Command) cmdAdd(args *skel.CmdArgs) error { + cfg, err := parseConfig(args.StdinData) + if err != nil { + return err + } + + // Get the values of args passed through CNI_ARGS. + cniArgs := CNIArgs{} + if err := types.LoadArgs(args.Args, &cniArgs); err != nil { + return err + } + + podNamespace := string(cniArgs.K8S_POD_NAMESPACE) + podName := string(cniArgs.K8S_POD_NAME) + + // We should never encounter this unless there has been an error in the kubelet. A good safeguard. + if podNamespace == "" || podName == "" { + return fmt.Errorf("not running in a pod, namespace and pod should have values") + } + + logPrefix := fmt.Sprintf("%s/%s", podNamespace, podName) + logger := hclog.New(&hclog.LoggerOptions{ + Name: logPrefix, + Level: hclog.LevelFromString(cfg.LogLevel), + }) + + // Check to see if the plugin is a chained plugin. + if cfg.PrevResult == nil { + return fmt.Errorf("must be called as final chained plugin") + } + + logger.Debug("consul-cni plugin config", "config", cfg) + // Convert the PrevResult to a concrete Result type that can be modified. The CNI standard says + // that the previous result needs to be passed onto the next plugin. + prevResult, err := current.GetResult(cfg.PrevResult) + if err != nil { + return fmt.Errorf("failed to convert prevResult: %w", err) + } + + if len(prevResult.IPs) == 0 { + return fmt.Errorf("got no container IPs") + } + + // Pass the prevResult through this plugin to the next one. + result := prevResult + logger.Debug("consul-cni previous result", "result", result) + + ctx := context.Background() + if c.client == nil { + + // Connect to kubernetes. + restConfig, err := clientcmd.BuildConfigFromFlags("", filepath.Join(cfg.CNINetDir, cfg.Kubeconfig)) + if err != nil { + return fmt.Errorf("could not get rest config from kubernetes api: %s", err) + } + + c.client, err = kubernetes.NewForConfig(restConfig) + if err != nil { + return fmt.Errorf("error initializing Kubernetes client: %s", err) + } + } + + pod, err := c.client.CoreV1().Pods(podNamespace).Get(ctx, podName, metav1.GetOptions{}) + if err != nil { + return fmt.Errorf("error retrieving pod: %s", err) + } + + // Skip traffic redirection if the correct annotations are not on the pod. + if skipTrafficRedirection(*pod) { + logger.Debug("skipping traffic redirection because the pod is either not injected or transparent proxy is disabled: %s", pod.Name) + return types.PrintResult(result, cfg.CNIVersion) + } + + // We do not throw an error here because kubernetes will often throw a benign error where the pod has been + // updated in between the get and update of the annotation. Eventually kubernetes will update the annotation + ok := c.updateTransparentProxyStatusAnnotation(pod, podNamespace, waiting) + if !ok { + logger.Info("unable to update %s pod annotation to waiting", keyTransparentProxyStatus) + } + + // Parse the cni-proxy-config annotation into an iptables.Config object. + iptablesCfg, err := parseAnnotation(*pod, annotationRedirectTraffic) + if err != nil { + return err + } + + // Set NetNS passed through the CNI. + iptablesCfg.NetNS = args.Netns + + // Set the provider to a fake provider in testing, otherwise use the default iptables.Provider + if c.iptablesProvider != nil { + iptablesCfg.IptablesProvider = c.iptablesProvider + } + + // Apply the iptables rules. + err = iptables.Setup(iptablesCfg) + if err != nil { + return fmt.Errorf("could not apply iptables setup: %v", err) + } + + // We do not throw an error here because kubernetes will often throw a benign error where the pod has been + // updated in between the get and update of the annotation. Eventually kubernetes will update the annotation + ok = c.updateTransparentProxyStatusAnnotation(pod, podNamespace, complete) + if !ok { + logger.Info("unable to update %s pod annotation to complete", keyTransparentProxyStatus) + } + + logger.Debug("traffic redirect rules applied to pod: %s", pod.Name) + // Pass through the result for the next plugin even though we are the final plugin in the chain. + return types.PrintResult(result, cfg.CNIVersion) +} + +// cmdDel is called for DELETE requests. +func cmdDel(_ *skel.CmdArgs) error { + // Nothing to do but this function will still be called as part of the CNI specification. + return nil +} + +// cmdCheck is called for CHECK requests. +func cmdCheck(_ *skel.CmdArgs) error { + // Nothing to do but this function will still be called as part of the CNI specification. + return nil +} + +func main() { + c := &Command{} + skel.PluginMain(c.cmdAdd, cmdCheck, cmdDel, version.All, bv.BuildString("consul-cni")) +} + +// skipTrafficRedirection looks for annotations on the pod and determines if it should skip traffic redirection. +// The absence of the annotations is the equivalent of "disabled" because it means that the connect inject mutating +// webhook did not run against the pod. +func skipTrafficRedirection(pod corev1.Pod) bool { + if anno, ok := pod.Annotations[keyInjectStatus]; !ok || anno == "" { + return true + } + + if anno, ok := pod.Annotations[keyTransparentProxyStatus]; !ok || anno == "" { + return true + } + return false +} + +// parseAnnotation parses the cni-proxy-config annotation into an iptables.Config object. +func parseAnnotation(pod corev1.Pod, annotation string) (iptables.Config, error) { + anno, ok := pod.Annotations[annotation] + if !ok { + return iptables.Config{}, fmt.Errorf("could not find %s annotation for %s pod", annotation, pod.Name) + } + cfg := iptables.Config{} + err := json.Unmarshal([]byte(anno), &cfg) + if err != nil { + return iptables.Config{}, fmt.Errorf("could not unmarshal %s annotation for %s pod", annotation, pod.Name) + } + return cfg, nil +} + +// updateTransparentProxyStatusAnnotation updates the transparent-proxy-status annotation. We use it as a simple inicator of +// CNI status on the pod. Failing is not fatal. +func (c *Command) updateTransparentProxyStatusAnnotation(pod *corev1.Pod, namespace, status string) bool { + pod.Annotations[keyTransparentProxyStatus] = status + _, err := c.client.CoreV1().Pods(namespace).Update(context.Background(), pod, metav1.UpdateOptions{}) + return err == nil +} diff --git a/control-plane/cni/main_test.go b/control-plane/cni/main_test.go new file mode 100644 index 0000000000..740e15c646 --- /dev/null +++ b/control-plane/cni/main_test.go @@ -0,0 +1,386 @@ +package main + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "testing" + + "github.com/containernetworking/cni/pkg/skel" + "github.com/hashicorp/consul/sdk/iptables" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/fake" +) + +const ( + defaultPodName = "fakePod" + defaultNamespace = "default" +) + +type fakeIptablesProvider struct { + rules []string +} + +func (f *fakeIptablesProvider) AddRule(name string, args ...string) { + var rule []string + rule = append(rule, name) + rule = append(rule, args...) + + f.rules = append(f.rules, strings.Join(rule, " ")) +} + +func (f *fakeIptablesProvider) ApplyRules() error { + return nil +} + +func (f *fakeIptablesProvider) Rules() []string { + return f.rules +} + +func Test_cmdAdd(t *testing.T) { + t.Parallel() + + cases := []struct { + name string + cmd *Command + podName string + stdInData string + configuredPod func(*corev1.Pod, *Command) *corev1.Pod + expectedRules bool + expectedErr error + }{ + { + name: "K8S_POD_NAME missing from CNI args, should throw error", + cmd: &Command{}, + podName: "", + stdInData: goodStdinData, + configuredPod: func(pod *corev1.Pod, cmd *Command) *corev1.Pod { + return pod + }, + expectedErr: fmt.Errorf("not running in a pod, namespace and pod should have values"), + expectedRules: false, // Rules won't be applied because the command will throw an error first + }, + { + name: "Missing prevResult in stdin data, should throw error", + cmd: &Command{ + client: fake.NewSimpleClientset(), + }, + podName: "missing-prev-result", + stdInData: missingPrevResultStdinData, + configuredPod: func(pod *corev1.Pod, cmd *Command) *corev1.Pod { + _, err := cmd.client.CoreV1().Pods(defaultNamespace).Create(context.Background(), pod, metav1.CreateOptions{}) + require.NoError(t, err) + + return pod + }, + expectedErr: fmt.Errorf("must be called as final chained plugin"), + expectedRules: false, // Rules won't be applied because the command will throw an error first + }, + { + name: "Missing IPs in prevResult in stdin data, should throw error", + cmd: &Command{ + client: fake.NewSimpleClientset(), + }, + podName: "corrupt-prev-result", + stdInData: missingIPsStdinData, + configuredPod: func(pod *corev1.Pod, cmd *Command) *corev1.Pod { + _, err := cmd.client.CoreV1().Pods(defaultNamespace).Create(context.Background(), pod, metav1.CreateOptions{}) + require.NoError(t, err) + + return pod + }, + expectedErr: fmt.Errorf("got no container IPs"), + expectedRules: false, // Rules won't be applied because the command will throw an error first + }, + { + name: "Pod with incorrect traffic redirection annotation, should throw error", + cmd: &Command{ + client: fake.NewSimpleClientset(), + }, + podName: "pod-with-incorrect-annotation", + stdInData: goodStdinData, + configuredPod: func(pod *corev1.Pod, cmd *Command) *corev1.Pod { + pod.Annotations[keyInjectStatus] = "true" + pod.Annotations[keyTransparentProxyStatus] = "enabled" + pod.Annotations[annotationRedirectTraffic] = "{foo}" + _, err := cmd.client.CoreV1().Pods(defaultNamespace).Create(context.Background(), pod, metav1.CreateOptions{}) + require.NoError(t, err) + + return pod + }, + expectedErr: fmt.Errorf("could not unmarshal %s annotation for %s pod", annotationRedirectTraffic, "pod-with-incorrect-annotation"), + expectedRules: false, // Rules won't be applied because the command will throw an error first + }, + { + name: "Pod with correct annotations, should create redirect traffic rules", + cmd: &Command{ + client: fake.NewSimpleClientset(), + iptablesProvider: &fakeIptablesProvider{}, + }, + podName: "pod-no-proxy-outbound-port", + stdInData: goodStdinData, + configuredPod: func(pod *corev1.Pod, cmd *Command) *corev1.Pod { + pod.Annotations[keyInjectStatus] = "true" + pod.Annotations[keyTransparentProxyStatus] = "enabled" + cfg := iptables.Config{ + ProxyUserID: "123", + ProxyInboundPort: 20000, + } + iptablesConfigJson, err := json.Marshal(&cfg) + require.NoError(t, err) + pod.Annotations[annotationRedirectTraffic] = string(iptablesConfigJson) + _, err = cmd.client.CoreV1().Pods(defaultNamespace).Create(context.Background(), pod, metav1.CreateOptions{}) + require.NoError(t, err) + + return pod + }, + expectedErr: nil, + expectedRules: true, // Rules will be applied + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + _ = c.configuredPod(minimalPod(c.podName), c.cmd) + err := c.cmd.cmdAdd(minimalSkelArgs(c.podName, defaultNamespace, c.stdInData)) + require.Equal(t, c.expectedErr, err) + + // Check to see that rules have been generated + if c.expectedErr == nil && c.expectedRules { + require.NotEmpty(t, c.cmd.iptablesProvider.Rules()) + } + }) + } +} + +func TestSkipTrafficRedirection(t *testing.T) { + t.Parallel() + cases := []struct { + name string + annotatedPod func(*corev1.Pod) *corev1.Pod + expectedSkip bool + }{ + { + name: "Pod with both annotations correctly set", + annotatedPod: func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[keyInjectStatus] = "foo" + pod.Annotations[keyTransparentProxyStatus] = "bar" + return pod + }, + expectedSkip: false, + }, + { + name: "Pod without annotations, will timeout waiting", + annotatedPod: func(pod *corev1.Pod) *corev1.Pod { + return pod + }, + expectedSkip: true, + }, + { + name: "Pod only with connect-inject-status annotation will skip because missing other annotation", + annotatedPod: func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[keyInjectStatus] = "foo" + return pod + }, + expectedSkip: true, + }, + { + name: "Pod with only transparent-proxy-status annotation will skip because missing other annotation", + annotatedPod: func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[keyTransparentProxyStatus] = "foo" + return pod + }, + expectedSkip: true, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + actual := skipTrafficRedirection(*c.annotatedPod(minimalPod(defaultPodName))) + require.Equal(t, c.expectedSkip, actual) + }) + } +} + +func TestParseAnnotation(t *testing.T) { + t.Parallel() + cases := []struct { + name string + annotation string + configurePod func(*corev1.Pod) *corev1.Pod + expected iptables.Config + err error + }{ + { + name: "Pod with iptables.Config annotation", + annotation: annotationRedirectTraffic, + configurePod: func(pod *corev1.Pod) *corev1.Pod { + // Use iptables.Config so that if the Config struct ever changes that the test is still valid + cfg := iptables.Config{ProxyUserID: "1234"} + j, err := json.Marshal(&cfg) + if err != nil { + t.Fatalf("could not marshal iptables config: %v", err) + } + pod.Annotations[annotationRedirectTraffic] = string(j) + return pod + }, + expected: iptables.Config{ + ProxyUserID: "1234", + }, + err: nil, + }, + { + name: "Pod without iptables.Config annotation", + annotation: annotationRedirectTraffic, + configurePod: func(pod *corev1.Pod) *corev1.Pod { + return pod + }, + expected: iptables.Config{}, + err: fmt.Errorf("could not find %s annotation for %s pod", annotationRedirectTraffic, defaultPodName), + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + actual, err := parseAnnotation(*c.configurePod(minimalPod(defaultPodName)), c.annotation) + require.Equal(t, c.expected, actual) + require.Equal(t, c.err, err) + }) + } +} + +func minimalPod(podName string) *corev1.Pod { + return &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: podName, + Annotations: map[string]string{}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "web", + }, + { + Name: "web-side", + }, + }, + }, + } +} + +func minimalSkelArgs(podName, namespace, stdinData string) *skel.CmdArgs { + return &skel.CmdArgs{ + ContainerID: "some-container-id", + Netns: "/some/netns/path", + IfName: "eth0", + Args: fmt.Sprintf("K8S_POD_NAME=%s;K8S_POD_NAMESPACE=%s", podName, namespace), + Path: "/some/bin/path", + StdinData: []byte(stdinData), + } +} + +const goodStdinData = `{ + "cniVersion": "0.3.1", + "name": "kindnet", + "type": "kindnet", + "capabilities": { + "testCapability": false + }, + "ipam": { + "type": "host-local" + }, + "dns": { + "nameservers": ["nameserver"], + "domain": "domain", + "search": ["search"], + "options": ["option"] + }, + "prevResult": { + "cniversion": "0.3.1", + "interfaces": [ + { + "name": "eth0", + "sandbox": "/tmp" + } + ], + "ips": [ + { + "version": "4", + "address": "10.0.0.2/24", + "gateway": "10.0.0.1", + "interface": 0 + } + ], + "routes": [] + + }, + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" +}` + +const missingPrevResultStdinData = `{ + "cniVersion": "0.3.1", + "name": "kindnet", + "type": "kindnet", + "capabilities": { + "testCapability": false + }, + "ipam": { + "type": "host-local" + }, + "dns": { + "nameservers": ["nameserver"], + "domain": "domain", + "search": ["search"], + "options": ["option"] + }, + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" +}` + +const missingIPsStdinData = `{ + "cniVersion": "0.3.1", + "name": "kindnet", + "type": "kindnet", + "capabilities": { + "testCapability": false + }, + "ipam": { + "type": "host-local" + }, + "dns": { + "nameservers": ["nameserver"], + "domain": "domain", + "search": ["search"], + "options": ["option"] + }, + "prevResult": { + "cniversion": "0.3.1", + "interfaces": [ + { + "name": "eth0", + "sandbox": "/tmp" + } + ], + "routes": [] + + }, + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" +}` diff --git a/control-plane/commands.go b/control-plane/commands.go index 8d5e8de23e..4b0afa6731 100644 --- a/control-plane/commands.go +++ b/control-plane/commands.go @@ -13,6 +13,7 @@ import ( cmdGetConsulClientCA "github.com/hashicorp/consul-k8s/control-plane/subcommand/get-consul-client-ca" cmdGossipEncryptionAutogenerate "github.com/hashicorp/consul-k8s/control-plane/subcommand/gossip-encryption-autogenerate" cmdInjectConnect "github.com/hashicorp/consul-k8s/control-plane/subcommand/inject-connect" + cmdInstallCNI "github.com/hashicorp/consul-k8s/control-plane/subcommand/install-cni" cmdPartitionInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/partition-init" cmdServerACLInit "github.com/hashicorp/consul-k8s/control-plane/subcommand/server-acl-init" cmdServiceAddress "github.com/hashicorp/consul-k8s/control-plane/subcommand/service-address" @@ -98,6 +99,9 @@ func init() { "gossip-encryption-autogenerate": func() (cli.Command, error) { return &cmdGossipEncryptionAutogenerate.Command{UI: ui}, nil }, + "install-cni": func() (cli.Command, error) { + return &cmdInstallCNI.Command{UI: ui}, nil + }, } } diff --git a/control-plane/connect-inject/annotations.go b/control-plane/connect-inject/annotations.go index 5c8545ee23..fa35959160 100644 --- a/control-plane/connect-inject/annotations.go +++ b/control-plane/connect-inject/annotations.go @@ -5,6 +5,10 @@ const ( // a pod after an injection is done. keyInjectStatus = "consul.hashicorp.com/connect-inject-status" + // keyTransparentProxyStatus is the key of the annotation that is added to + // a pod when transparent proxy is done. + keyTransparentProxyStatus = "consul.hashicorp.com/transparent-proxy-status" + // keyManagedBy is the key of the label that is added to pods managed // by the Endpoints controller. This is to support upgrading from consul-k8s // without Endpoints controller to consul-k8s with Endpoints controller @@ -148,6 +152,10 @@ const ( // to point to the Envoy proxy when running in Transparent Proxy mode. annotationTransparentProxyOverwriteProbes = "consul.hashicorp.com/transparent-proxy-overwrite-probes" + // annotationRedirectTraffic stores iptables.Config information so that the CNI plugin can use it to apply + // iptables rules. + annotationRedirectTraffic = "consul.hashicorp.com/redirect-traffic-config" + // annotationOriginalPod is the value of the pod before being overwritten by the consul // webhook/meshWebhook. annotationOriginalPod = "consul.hashicorp.com/original-pod" @@ -164,9 +172,12 @@ const ( // by the peering controllers. labelPeeringToken = "consul.hashicorp.com/peering-token" - // injected is used as the annotation value for annotationInjected. + // injected is used as the annotation value for keyInjectStatus and annotationInjected. injected = "injected" + // enabled is used as the annotation value for keyTransparentProxyStatus. + enabled = "enabled" + // endpointsController is the value for keyManagedBy. managedByValue = "consul-k8s-endpoints-controller" ) diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index a1550b3da7..e0ef413011 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -14,13 +14,13 @@ import ( ) const ( - InjectInitCopyContainerName = "copy-consul-bin" - InjectInitContainerName = "consul-connect-inject-init" - rootUserAndGroupID = 0 - envoyUserAndGroupID = 5995 - copyContainerUserAndGroupID = 5996 - netAdminCapability = "NET_ADMIN" - dnsServiceHostEnvSuffix = "DNS_SERVICE_HOST" + InjectInitCopyContainerName = "copy-consul-bin" + InjectInitContainerName = "consul-connect-inject-init" + rootUserAndGroupID = 0 + envoyUserAndGroupID = 5995 + initContainersUserAndGroupID = 5996 + netAdminCapability = "NET_ADMIN" + dnsServiceHostEnvSuffix = "DNS_SERVICE_HOST" ) type initContainerCommandData struct { @@ -61,6 +61,10 @@ type initContainerCommandData struct { // container to do that. EnableTransparentProxy bool + // EnableCNI configures this init container to skip the redirect-traffic command as traffic + // redirection is handled by the CNI plugin on pod creation. + EnableCNI bool + // TProxyExcludeInboundPorts is a list of inbound ports to exclude from traffic redirection via // the consul connect redirect-traffic command. TProxyExcludeInboundPorts []string @@ -118,8 +122,8 @@ func (w *MeshWebhook) initCopyContainer() corev1.Container { if !w.EnableOpenShift { container.SecurityContext = &corev1.SecurityContext{ // Set RunAsUser because the default user for the consul container is root and we want to run non-root. - RunAsUser: pointer.Int64(copyContainerUserAndGroupID), - RunAsGroup: pointer.Int64(copyContainerUserAndGroupID), + RunAsUser: pointer.Int64(initContainersUserAndGroupID), + RunAsGroup: pointer.Int64(initContainersUserAndGroupID), RunAsNonRoot: pointer.Bool(true), ReadOnlyRootFilesystem: pointer.Bool(true), } @@ -161,6 +165,7 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, NamespaceMirroringEnabled: w.EnableK8SNSMirroring, ConsulCACert: w.ConsulCACert, EnableTransparentProxy: tproxyEnabled, + EnableCNI: w.EnableCNI, TProxyExcludeInboundPorts: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeInboundPorts, pod), TProxyExcludeOutboundPorts: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundPorts, pod), TProxyExcludeOutboundCIDRs: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundCIDRs, pod), @@ -297,15 +302,27 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, if tproxyEnabled { // Running consul connect redirect-traffic with iptables // requires both being a root user and having NET_ADMIN capability. - container.SecurityContext = &corev1.SecurityContext{ - RunAsUser: pointer.Int64(rootUserAndGroupID), - RunAsGroup: pointer.Int64(rootUserAndGroupID), - // RunAsNonRoot overrides any setting in the Pod so that we can still run as root here as required. - RunAsNonRoot: pointer.Bool(false), - Privileged: pointer.Bool(true), - Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{netAdminCapability}, - }, + if !w.EnableCNI { + container.SecurityContext = &corev1.SecurityContext{ + RunAsUser: pointer.Int64(rootUserAndGroupID), + RunAsGroup: pointer.Int64(rootUserAndGroupID), + // RunAsNonRoot overrides any setting in the Pod so that we can still run as root here as required. + RunAsNonRoot: pointer.Bool(false), + Privileged: pointer.Bool(true), + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{netAdminCapability}, + }, + } + } else { + container.SecurityContext = &corev1.SecurityContext{ + RunAsUser: pointer.Int64(initContainersUserAndGroupID), + RunAsGroup: pointer.Int64(initContainersUserAndGroupID), + RunAsNonRoot: pointer.Bool(true), + Privileged: pointer.Bool(false), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + } } } @@ -457,6 +474,7 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD {{- if .EnableTransparentProxy }} +{{- if not .EnableCNI }} {{- /* The newline below is intentional to allow extra space in the rendered template between this and the previous commands. */}} @@ -489,4 +507,5 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -proxy-id="$(cat /consul/connect-inject/proxyid)" \ -proxy-uid={{ .EnvoyUID }} {{- end }} +{{- end }} ` diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index 56b4f2192a..22f14c1f73 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -228,13 +228,15 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD func TestHandlerContainerInit_transparentProxy(t *testing.T) { cases := map[string]struct { globalEnabled bool + cniEnabled bool annotations map[string]string expectedContainsCmd string expectedNotContainsCmd string namespaceLabel map[string]string }{ - "enabled globally, ns not set, annotation not provided": { + "enabled globally, ns not set, annotation not provided, cni disabled": { true, + false, nil, `/consul/connect-inject/consul connect redirect-traffic \ -proxy-id="$(cat /consul/connect-inject/proxyid)" \ @@ -242,8 +244,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "enabled globally, ns not set, annotation is false": { + "enabled globally, ns not set, annotation is false, cni disabled": { true, + false, map[string]string{keyTransparentProxy: "false"}, "", `/consul/connect-inject/consul connect redirect-traffic \ @@ -251,8 +254,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { -proxy-uid=5995`, nil, }, - "enabled globally, ns not set, annotation is true": { + "enabled globally, ns not set, annotation is true, cni disabled": { true, + false, map[string]string{keyTransparentProxy: "true"}, `/consul/connect-inject/consul connect redirect-traffic \ -proxy-id="$(cat /consul/connect-inject/proxyid)" \ @@ -260,7 +264,8 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "disabled globally, ns not set, annotation not provided": { + "disabled globally, ns not set, annotation not provided, cni disabled": { + false, false, nil, "", @@ -269,7 +274,8 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { -proxy-uid=5995`, nil, }, - "disabled globally, ns not set, annotation is false": { + "disabled globally, ns not set, annotation is false, cni disabled": { + false, false, map[string]string{keyTransparentProxy: "false"}, "", @@ -278,7 +284,8 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { -proxy-uid=5995`, nil, }, - "disabled globally, ns not set, annotation is true": { + "disabled globally, ns not set, annotation is true, cni disabled": { + false, false, map[string]string{keyTransparentProxy: "true"}, `/consul/connect-inject/consul connect redirect-traffic \ @@ -287,8 +294,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "exclude-inbound-ports, ns is not set, annotation is provided": { + "exclude-inbound-ports, ns is not set, annotation is provided, cni disabled": { true, + false, map[string]string{ keyTransparentProxy: "true", annotationTProxyExcludeInboundPorts: "9090,9091", @@ -301,8 +309,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "exclude-outbound-ports, ns is not set, annotation is provided": { + "exclude-outbound-ports, ns is not set, annotation is provided, cni disabled": { true, + false, map[string]string{ keyTransparentProxy: "true", annotationTProxyExcludeOutboundPorts: "9090,9091", @@ -315,8 +324,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "exclude-outbound-cidrs annotation is provided": { + "exclude-outbound-cidrs annotation is provided, cni disabled": { true, + false, map[string]string{ keyTransparentProxy: "true", annotationTProxyExcludeOutboundCIDRs: "1.1.1.1,2.2.2.2/24", @@ -329,8 +339,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "exclude-uids annotation is provided, ns is not set": { + "exclude-uids annotation is provided, ns is not set, cni disabled": { true, + false, map[string]string{ keyTransparentProxy: "true", annotationTProxyExcludeUIDs: "6000,7000", @@ -343,7 +354,8 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", nil, }, - "disabled globally, ns enabled, annotation not set": { + "disabled globally, ns enabled, annotation not set, cni disabled": { + false, false, nil, `/consul/connect-inject/consul connect redirect-traffic \ @@ -352,8 +364,9 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { "", map[string]string{keyTransparentProxy: "true"}, }, - "enabled globally, ns disabled, annotation not set": { + "enabled globally, ns disabled, annotation not set, cni disabled": { true, + false, nil, "", `/consul/connect-inject/consul connect redirect-traffic \ @@ -361,24 +374,56 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { -proxy-uid=5995`, map[string]string{keyTransparentProxy: "false"}, }, + "disabled globally, ns enabled, annotation not set, cni enabled": { + false, + true, + nil, + "", + `/consul/connect-inject/consul connect redirect-traffic \ + -proxy-id="$(cat /consul/connect-inject/proxyid)" \ + -proxy-uid=5995`, + map[string]string{keyTransparentProxy: "true"}, + }, + + "enabled globally, ns not set, annotation not set, cni enabled": { + true, + true, + nil, + "", + `/consul/connect-inject/consul connect redirect-traffic \ + -proxy-id="$(cat /consul/connect-inject/proxyid)" \ + -proxy-uid=5995`, + nil, + }, } for name, c := range cases { t.Run(name, func(t *testing.T) { w := MeshWebhook{ EnableTransparentProxy: c.globalEnabled, ConsulAPITimeout: 5 * time.Second, + EnableCNI: c.cniEnabled, } pod := minimal() pod.Annotations = c.annotations - expectedSecurityContext := &corev1.SecurityContext{ - RunAsUser: pointer.Int64(0), - RunAsGroup: pointer.Int64(0), - Privileged: pointer.Bool(true), - Capabilities: &corev1.Capabilities{ + expectedSecurityContext := &corev1.SecurityContext{} + if !c.cniEnabled { + expectedSecurityContext.RunAsUser = pointer.Int64(0) + expectedSecurityContext.RunAsGroup = pointer.Int64(0) + expectedSecurityContext.RunAsNonRoot = pointer.Bool(false) + expectedSecurityContext.Privileged = pointer.Bool(true) + expectedSecurityContext.Capabilities = &corev1.Capabilities{ Add: []corev1.Capability{netAdminCapability}, - }, - RunAsNonRoot: pointer.Bool(false), + } + } else { + + expectedSecurityContext.RunAsUser = pointer.Int64(initContainersUserAndGroupID) + expectedSecurityContext.RunAsGroup = pointer.Int64(initContainersUserAndGroupID) + expectedSecurityContext.RunAsNonRoot = pointer.Bool(true) + expectedSecurityContext.Privileged = pointer.Bool(false) + expectedSecurityContext.Capabilities = &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + } } ns := testNS ns.Labels = c.namespaceLabel @@ -390,7 +435,11 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { require.Equal(t, expectedSecurityContext, container.SecurityContext) require.Contains(t, actualCmd, c.expectedContainsCmd) } else { - require.Nil(t, container.SecurityContext) + if !c.cniEnabled { + require.Nil(t, container.SecurityContext) + } else { + require.Equal(t, expectedSecurityContext, container.SecurityContext) + } require.NotContains(t, actualCmd, c.expectedNotContainsCmd) } }) @@ -917,7 +966,8 @@ func TestHandlerContainerInit_Multiport(t *testing.T) { serviceName: "web-admin", }, }, - []string{`/bin/sh -ec + []string{ + `/bin/sh -ec export CONSUL_HTTP_ADDR="${HOST_IP}:8500" export CONSUL_GRPC_ADDR="${HOST_IP}:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ @@ -968,7 +1018,8 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD serviceName: "web-admin", }, }, - []string{`/bin/sh -ec + []string{ + `/bin/sh -ec export CONSUL_HTTP_ADDR="${HOST_IP}:8500" export CONSUL_GRPC_ADDR="${HOST_IP}:8502" consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ @@ -1167,8 +1218,8 @@ func TestHandlerInitCopyContainer(t *testing.T) { require.Nil(t, container.SecurityContext) } else { expectedSecurityContext := &corev1.SecurityContext{ - RunAsUser: pointer.Int64(copyContainerUserAndGroupID), - RunAsGroup: pointer.Int64(copyContainerUserAndGroupID), + RunAsUser: pointer.Int64(initContainersUserAndGroupID), + RunAsGroup: pointer.Int64(initContainersUserAndGroupID), RunAsNonRoot: pointer.Bool(true), ReadOnlyRootFilesystem: pointer.Bool(true), } diff --git a/control-plane/connect-inject/endpoints_controller.go b/control-plane/connect-inject/endpoints_controller.go index f91b306571..04c8e70a26 100644 --- a/control-plane/connect-inject/endpoints_controller.go +++ b/control-plane/connect-inject/endpoints_controller.go @@ -57,6 +57,9 @@ const ( // exposedPathsStartupPortsRangeStart is the start of the port range that we will use as // the ListenerPort for the Expose configuration of the proxy registration for a startup probe. exposedPathsStartupPortsRangeStart = 20500 + + // proxyDefaultInboundPort is the default inbound port for the proxy. + proxyDefaultInboundPort = 20000 ) type EndpointsController struct { @@ -182,7 +185,8 @@ func (r *EndpointsController) Reconcile(ctx context.Context, req ctrl.Request) ( serviceName, ok := pod.Annotations[annotationKubernetesService] if ok && serviceEndpoints.Name != serviceName { r.Log.Info("ignoring endpoint because it doesn't match explicit service annotation", "name", serviceEndpoints.Name, "ns", serviceEndpoints.Namespace) - // deregistration for service instances that don't match the annotation happens later because we don't add this pod to the endpointAddressMap. + // deregistration for service instances that don't match the annotation happens + // later because we don't add this pod to the endpointAddressMap. continue } @@ -287,7 +291,6 @@ func (r *EndpointsController) registerServicesAndHealthCheck(pod corev1.Pod, ser return err } } - return nil } @@ -493,7 +496,7 @@ func (r *EndpointsController) createServiceRegistrations(pod corev1.Pod, service } proxyConfig.Upstreams = upstreams - proxyPort := 20000 + proxyPort := proxyDefaultInboundPort if idx := getMultiPortIdx(pod, serviceEndpoints); idx >= 0 { proxyPort += idx } @@ -636,7 +639,6 @@ func (r *EndpointsController) createServiceRegistrations(pod corev1.Pod, service } } } - return service, proxyService, nil } @@ -901,7 +903,6 @@ func processPreparedQueryUpstream(pod corev1.Pod, rawUpstream string) api.Upstre preparedQuery = strings.TrimSpace(parts[1]) var upstream api.Upstream if port > 0 { - upstream = api.Upstream{ DestinationType: api.UpstreamDestTypePreparedQuery, DestinationName: preparedQuery, @@ -974,7 +975,6 @@ func (r *EndpointsController) processUnlabeledUpstream(pod corev1.Pod, rawUpstre } } return upstream, nil - } // processLabeledUpstream processes an upstream in the format: @@ -1023,7 +1023,6 @@ func (r *EndpointsController) processLabeledUpstream(pod corev1.Pod, rawUpstream default: return api.Upstream{}, fmt.Errorf("upstream structured incorrectly: %s", rawUpstream) } - } else { switch len(pieces) { case 4: @@ -1042,7 +1041,6 @@ func (r *EndpointsController) processLabeledUpstream(pod corev1.Pod, rawUpstream default: return api.Upstream{}, fmt.Errorf("upstream structured incorrectly: %s", rawUpstream) } - } if port > 0 { @@ -1057,7 +1055,6 @@ func (r *EndpointsController) processLabeledUpstream(pod corev1.Pod, rawUpstream } } return upstream, nil - } // remoteConsulClient returns an *api.Client that points at the consul agent local to the pod for a provided namespace. diff --git a/control-plane/connect-inject/mesh_webhook.go b/control-plane/connect-inject/mesh_webhook.go index cd1e49cd25..eef1187835 100644 --- a/control-plane/connect-inject/mesh_webhook.go +++ b/control-plane/connect-inject/mesh_webhook.go @@ -25,11 +25,9 @@ import ( "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) -var ( - // kubeSystemNamespaces is a set of namespaces that are considered - // "system" level namespaces and are always skipped (never injected). - kubeSystemNamespaces = mapset.NewSetWith(metav1.NamespaceSystem, metav1.NamespacePublic) -) +// kubeSystemNamespaces is a set of namespaces that are considered +// "system" level namespaces and are always skipped (never injected). +var kubeSystemNamespaces = mapset.NewSetWith(metav1.NamespaceSystem, metav1.NamespacePublic) // Webhook is the HTTP meshWebhook for admission webhooks. type MeshWebhook struct { @@ -136,6 +134,11 @@ type MeshWebhook struct { // so that all traffic will go through the Envoy proxy. EnableTransparentProxy bool + // EnableCNI enables the CNI plugin and prevents the connect-inject init container + // from running the consul redirect-traffic command as the CNI plugin handles traffic + // redirection + EnableCNI bool + // TProxyOverwriteProbes controls whether the webhook should mutate pod's HTTP probes // to point them to the Envoy proxy. TProxyOverwriteProbes bool @@ -362,6 +365,18 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi // and does not need to be checked for being a nil value. pod.Annotations[keyInjectStatus] = injected + tproxyEnabled, err := transparentProxyEnabled(*ns, pod, w.EnableTransparentProxy) + if err != nil { + w.Log.Error(err, "error determining if transparent proxy is enabled", "request name", req.Name) + return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error determining if transparent proxy is enabled: %s", err)) + } + + // Add an annotation to the pod sets transparent-proxy-status to enabled or disabled. Used by the CNI plugin + // to determine if it should traffic redirect or not + if tproxyEnabled { + pod.Annotations[keyTransparentProxyStatus] = enabled + } + // Add annotations for metrics. if err = w.prometheusAnnotations(&pod); err != nil { w.Log.Error(err, "error configuring prometheus annotations", "request name", req.Name) @@ -389,6 +404,16 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error overwriting readiness or liveness probes: %s", err)) } + // When CNI and tproxy are enabled, we add an annotation to the pod that contains the iptables config so that the CNI + // plugin can apply redirect traffic rules on the pod. + if w.EnableCNI && tproxyEnabled { + if err := w.addRedirectTrafficConfigAnnotation(&pod, *ns); err != nil { + // todo: update this error message + w.Log.Error(err, "error configuring annotation for CNI traffic redirection", "request name", req.Name) + return admission.Errored(http.StatusInternalServerError, fmt.Errorf("error configuring annotation for CNI traffic redirection: %s", err)) + } + } + // Marshall the pod into JSON after it has the desired envs, annotations, labels, // sidecars and initContainers appended to it. updatedPodJson, err := json.Marshal(pod) diff --git a/control-plane/connect-inject/mesh_webhook_test.go b/control-plane/connect-inject/mesh_webhook_test.go index 8b37462506..0f21b6dca7 100644 --- a/control-plane/connect-inject/mesh_webhook_test.go +++ b/control-plane/connect-inject/mesh_webhook_test.go @@ -718,6 +718,11 @@ func TestHandlerHandle(t *testing.T) { Operation: "add", Path: "/metadata/annotations/" + escapeJSONPointer(keyInjectStatus), }, + { + Operation: "add", + Path: "/metadata/annotations/" + escapeJSONPointer(keyTransparentProxyStatus), + }, + { Operation: "add", Path: "/metadata/annotations/" + escapeJSONPointer(annotationOriginalPod), @@ -1868,7 +1873,6 @@ func TestOverwriteProbes(t *testing.T) { require.Equal(t, c.expStartupPort[i], container.StartupProbe.HTTPGet.Port.IntValue()) } } - }) } } @@ -1904,9 +1908,7 @@ func TestHandler_checkUnsupportedMultiPortCases(t *testing.T) { require.Error(t, err) require.Equal(t, tt.expErr, err.Error()) }) - } - } // encodeRaw is a helper to encode some data into a RawExtension. diff --git a/control-plane/connect-inject/redirect_traffic.go b/control-plane/connect-inject/redirect_traffic.go new file mode 100644 index 0000000000..895b5befbe --- /dev/null +++ b/control-plane/connect-inject/redirect_traffic.go @@ -0,0 +1,115 @@ +package connectinject + +import ( + "encoding/json" + "fmt" + "os" + "strconv" + + "github.com/hashicorp/consul/sdk/iptables" + corev1 "k8s.io/api/core/v1" +) + +// addRedirectTrafficConfigAnnotation creates an iptables.Config based on proxy configuration. +// iptables.Config: +// ConsulDNSIP: an environment variable named RESOURCE_PREFIX_DNS_SERVICE_HOST where RESOURCE_PREFIX is the consul.fullname in helm. +// ProxyUserID: a constant set in Annotations +// ProxyInboundPort: the service port or bind port +// ProxyOutboundPort: default transparent proxy outbound port or transparent proxy outbound listener port +// ExcludeInboundPorts: prometheus, envoy stats, expose paths, checks and excluded pod annotations +// ExcludeOutboundPorts: pod annotations +// ExcludeOutboundCIDRs: pod annotations +// ExcludeUIDs: pod annotations +func (w *MeshWebhook) addRedirectTrafficConfigAnnotation(pod *corev1.Pod, ns corev1.Namespace) error { + cfg := iptables.Config{ + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + } + + // Set the proxy's inbound port. + cfg.ProxyInboundPort = proxyDefaultInboundPort + + // Set the proxy's outbound port. + cfg.ProxyOutboundPort = iptables.DefaultTProxyOutboundPort + + // If metrics are enabled, get the prometheusScrapePort and exclude it from the inbound ports + enableMetrics, err := w.MetricsConfig.enableMetrics(*pod) + if err != nil { + return err + } + if enableMetrics { + prometheusScrapePort, err := w.MetricsConfig.prometheusScrapePort(*pod) + if err != nil { + return err + } + cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, prometheusScrapePort) + } + + // Exclude any overwritten liveness/readiness/startup ports from redirection. + overwriteProbes, err := shouldOverwriteProbes(*pod, w.TProxyOverwriteProbes) + if err != nil { + return err + } + + if overwriteProbes { + for i, container := range pod.Spec.Containers { + // skip the "envoy-sidecar" container from having its probes overridden + if container.Name == envoySidecarContainer { + continue + } + if container.LivenessProbe != nil && container.LivenessProbe.HTTPGet != nil { + cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, strconv.Itoa(exposedPathsLivenessPortsRangeStart+i)) + } + if container.ReadinessProbe != nil && container.ReadinessProbe.HTTPGet != nil { + cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, strconv.Itoa(exposedPathsReadinessPortsRangeStart+i)) + } + if container.StartupProbe != nil && container.StartupProbe.HTTPGet != nil { + cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, strconv.Itoa(exposedPathsStartupPortsRangeStart+i)) + } + } + } + + // Inbound ports + excludeInboundPorts := splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeInboundPorts, *pod) + cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, excludeInboundPorts...) + + // Outbound ports + excludeOutboundPorts := splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundPorts, *pod) + cfg.ExcludeOutboundPorts = append(cfg.ExcludeOutboundPorts, excludeOutboundPorts...) + + // Outbound CIDRs + excludeOutboundCIDRs := splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundCIDRs, *pod) + cfg.ExcludeOutboundCIDRs = append(cfg.ExcludeOutboundCIDRs, excludeOutboundCIDRs...) + + // UIDs + excludeUIDs := splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeUIDs, *pod) + cfg.ExcludeUIDs = append(cfg.ExcludeUIDs, excludeUIDs...) + + // Add init container user ID to exclude from traffic redirection. + cfg.ExcludeUIDs = append(cfg.ExcludeUIDs, strconv.Itoa(initContainersUserAndGroupID)) + + dnsEnabled, err := consulDNSEnabled(ns, *pod, w.EnableConsulDNS) + if err != nil { + return err + } + + var consulDNSClusterIP string + if dnsEnabled { + // If Consul DNS is enabled, we find the environment variable that has the value + // of the ClusterIP of the Consul DNS Service. constructDNSServiceHostName returns + // the name of the env variable whose value is the ClusterIP of the Consul DNS Service. + consulDNSClusterIP = os.Getenv(w.constructDNSServiceHostName()) + if consulDNSClusterIP == "" { + return fmt.Errorf("environment variable %s not found", w.constructDNSServiceHostName()) + } + cfg.ConsulDNSIP = consulDNSClusterIP + } + + iptablesConfigJson, err := json.Marshal(&cfg) + if err != nil { + return fmt.Errorf("could not marshal iptables config: %w", err) + } + + pod.Annotations[annotationRedirectTraffic] = string(iptablesConfigJson) + + return nil +} diff --git a/control-plane/connect-inject/redirect_traffic_test.go b/control-plane/connect-inject/redirect_traffic_test.go new file mode 100644 index 0000000000..838f1c0c25 --- /dev/null +++ b/control-plane/connect-inject/redirect_traffic_test.go @@ -0,0 +1,447 @@ +package connectinject + +import ( + "encoding/json" + "fmt" + "os" + "strconv" + "testing" + + mapset "github.com/deckarep/golang-set" + logrtest "github.com/go-logr/logr/testing" + "github.com/hashicorp/consul/sdk/iptables" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +const ( + defaultPodName = "fakePod" + defaultNamespace = "default" + resourcePrefix = "CONSUL" + dnsEnvVariable = "CONSUL_DNS_SERVICE_HOST" + dnsIP = "127.0.0.1" +) + +func TestAddRedirectTrafficConfig(t *testing.T) { + s := runtime.NewScheme() + s.AddKnownTypes(schema.GroupVersion{ + Group: "", + Version: "v1", + }, &corev1.Pod{}) + decoder, err := admission.NewDecoder(s) + require.NoError(t, err) + cases := []struct { + name string + webhook MeshWebhook + pod *corev1.Pod + namespace corev1.Namespace + dnsEnabled bool + expCfg iptables.Config + expErr error + }{ + { + name: "basic bare minimum pod", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + }, + }, + { + name: "metrics enabled", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationEnableMetrics: "true", + annotationPrometheusScrapePort: "13373", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + ExcludeInboundPorts: []string{"13373"}, + }, + }, + { + name: "metrics enabled with incorrect annotation", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationEnableMetrics: "invalid", + annotationPrometheusScrapePort: "13373", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + ExcludeInboundPorts: []string{"13373"}, + }, + expErr: fmt.Errorf("%s annotation value of %s was invalid: %s", annotationEnableMetrics, "invalid", "strconv.ParseBool: parsing \"invalid\": invalid syntax"), + }, + { + name: "overwrite probes, transparent proxy annotation set", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationTransparentProxyOverwriteProbes: "true", + keyTransparentProxy: "true", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + LivenessProbe: &corev1.Probe{ + Handler: corev1.Handler{ + HTTPGet: &corev1.HTTPGetAction{ + Port: intstr.FromInt(exposedPathsLivenessPortsRangeStart), + }, + }, + }, + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + ExcludeInboundPorts: []string{strconv.Itoa(exposedPathsLivenessPortsRangeStart)}, + }, + }, + { + name: "exclude inbound ports", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationTProxyExcludeInboundPorts: "1111,11111", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + ExcludeInboundPorts: []string{"1111", "11111"}, + }, + }, + { + name: "exclude outbound ports", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationTProxyExcludeOutboundPorts: "2222,22222", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + ExcludeOutboundPorts: []string{"2222", "22222"}, + }, + }, + { + name: "exclude outbound CIDRs", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationTProxyExcludeOutboundCIDRs: "3.3.3.3,3.3.3.3/24", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{strconv.Itoa(initContainersUserAndGroupID)}, + ExcludeOutboundCIDRs: []string{"3.3.3.3", "3.3.3.3/24"}, + }, + }, + { + name: "exclude UIDs", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationTProxyExcludeUIDs: "4444,44444", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"4444", "44444", strconv.Itoa(initContainersUserAndGroupID)}, + }, + }, + { + name: "exclude inbound ports, outbound ports, outbound CIDRs, and UIDs", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationTProxyExcludeInboundPorts: "1111,11111", + annotationTProxyExcludeOutboundPorts: "2222,22222", + annotationTProxyExcludeOutboundCIDRs: "3.3.3.3,3.3.3.3/24", + annotationTProxyExcludeUIDs: "4444,44444", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeInboundPorts: []string{"1111", "11111"}, + ExcludeOutboundPorts: []string{"2222", "22222"}, + ExcludeOutboundCIDRs: []string{"3.3.3.3", "3.3.3.3/24"}, + ExcludeUIDs: []string{"4444", "44444", strconv.Itoa(initContainersUserAndGroupID)}, + }, + }, + { + name: "dns enabled", + dnsEnabled: true, + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + ResourcePrefix: resourcePrefix, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + keyConsulDNS: "true", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: dnsIP, + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{strconv.Itoa(initContainersUserAndGroupID)}, + }, + }, + { + name: "dns annotation set but environment variable missing", + dnsEnabled: false, + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + ResourcePrefix: resourcePrefix, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + keyConsulDNS: "true", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: dnsIP, + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{strconv.Itoa(initContainersUserAndGroupID)}, + }, + expErr: fmt.Errorf("environment variable %s not found", dnsEnvVariable), + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + if c.dnsEnabled { + os.Setenv(dnsEnvVariable, dnsIP) + } else { + os.Setenv(dnsEnvVariable, "") + } + err := c.webhook.addRedirectTrafficConfigAnnotation(c.pod, c.namespace) + require.Equal(t, c.expErr, err) + + // Only compare annotation and iptables config on successful runs + if c.expErr == nil { + anno, ok := c.pod.Annotations[annotationRedirectTraffic] + require.Equal(t, ok, true) + + actualConfig := iptables.Config{} + json.Unmarshal([]byte(anno), &actualConfig) + require.Equal(t, c.expCfg, actualConfig) + } + }) + } +} diff --git a/control-plane/go.mod b/control-plane/go.mod index bc8edd48ea..1be842ad95 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -1,11 +1,14 @@ module github.com/hashicorp/consul-k8s/control-plane require ( - github.com/cenkalti/backoff v2.1.1+incompatible + github.com/cenkalti/backoff v2.2.1+incompatible + github.com/containernetworking/cni v1.1.1 github.com/deckarep/golang-set v1.7.1 + github.com/fsnotify/fsnotify v1.5.4 github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 + github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f @@ -17,10 +20,10 @@ require ( github.com/mitchellh/cli v1.1.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.4.1 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.7.1 go.uber.org/zap v1.19.0 golang.org/x/text v0.3.7 - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 gomodules.xyz/jsonpatch/v2 v2.2.0 k8s.io/api v0.22.2 k8s.io/apimachinery v0.22.2 @@ -31,7 +34,7 @@ require ( ) require ( - cloud.google.com/go v0.54.0 // indirect + cloud.google.com/go v0.81.0 // indirect github.com/Azure/azure-sdk-for-go v44.0.0+incompatible // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.18 // indirect @@ -53,10 +56,9 @@ require ( github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 // indirect github.com/digitalocean/godo v1.10.0 // indirect github.com/dimchansky/utfbom v1.1.0 // indirect - github.com/evanphx/json-patch v4.11.0+incompatible // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/fatih/color v1.12.0 // indirect github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-logr/zapr v0.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -78,13 +80,13 @@ require ( github.com/imdario/mergo v0.3.12 // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect github.com/joyent/triton-go v1.7.1-0.20200416154420-6801d15b779f // indirect - github.com/json-iterator/go v1.1.11 // indirect + github.com/json-iterator/go v1.1.12 // indirect github.com/linode/linodego v0.7.1 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mattn/go-isatty v0.0.13 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-isatty v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nicolai86/scaleway-sdk v1.10.2-0.20180628010248-798f60e20bb2 // indirect github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c // indirect github.com/pkg/errors v0.9.1 // indirect @@ -101,21 +103,21 @@ require ( github.com/stretchr/objx v0.2.0 // indirect github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible // indirect github.com/vmware/govmomi v0.18.0 // indirect - go.opencensus.io v0.22.3 // indirect + go.opencensus.io v0.23.0 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect + golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d // indirect + golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/api v0.20.0 // indirect + google.golang.org/api v0.43.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect google.golang.org/grpc v1.38.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/resty.v1 v1.12.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/control-plane/go.sum b/control-plane/go.sum index 8be9787ae3..b42a9dca6b 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -8,20 +8,35 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/Azure/azure-sdk-for-go v44.0.0+incompatible h1:e82Yv2HNpS0kuyeCrV29OPKvEiqfs2/uJHic3/3iKdg= github.com/Azure/azure-sdk-for-go v44.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= @@ -100,8 +115,8 @@ github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= @@ -115,11 +130,14 @@ github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6D github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/containernetworking/cni v1.1.1 h1:ky20T7c0MvKvbMOwS/FrlbNwjEoqJEUUYfsL4b0mc4k= +github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -159,13 +177,15 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= +github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= @@ -175,8 +195,9 @@ github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoD github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -226,12 +247,16 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -252,7 +277,11 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= @@ -264,11 +293,20 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= @@ -295,6 +333,8 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a h1:cBwGTYV84M0W8PwHX6+PywY8NiP3dzA7JaZzs9+LdiA= +github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a/go.mod h1:aw35GB76URgbtxaSSMxbOetbG7YEHHPkIX3/SkTBaWc= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 h1:csNww5qBHaFqsX1eMEKVvmJ4dhqcXWj0sCkbccsSsHc= github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= @@ -358,6 +398,7 @@ github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyu github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= @@ -381,8 +422,9 @@ github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCV github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -414,15 +456,16 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.13 h1:qdl+GuBjcsKKDco5BsxPJlId98mSWNKqYA+Co0SC1yA= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= @@ -451,8 +494,9 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= @@ -474,12 +518,15 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= +github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c h1:vwpFWvAO8DeIZfFeqASzZfsxuWPno9ncAebBEP0N3uE= github.com/packethost/packngo v0.1.1-0.20180711074735-b9cb5096f54c/go.mod h1:otzZQXgoO96RTzDB/Hycg0qZcXZsWJGJRSXbmEIJ+4M= @@ -580,8 +627,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible h1:8uRvJleFpqLsO77WaAh2UrasMOzd8MxXrNj20e7El+Q= github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= @@ -594,7 +642,9 @@ github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -609,8 +659,11 @@ go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVd go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= @@ -673,6 +726,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= @@ -683,6 +737,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -702,6 +758,7 @@ golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -713,30 +770,50 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= @@ -782,35 +859,54 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I= +golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= @@ -819,8 +915,9 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -858,11 +955,27 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -881,13 +994,25 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0 h1:jz2KixHX7EcCPiQrySzPdnYT7DbINAypCqKZ1Z7GM40= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0 h1:4sAyIHT6ZohtAQDoxws+ez7bROYmUlOVvsUscYCDTqA= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -907,11 +1032,31 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -923,9 +1068,17 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= @@ -940,8 +1093,9 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -983,6 +1137,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= diff --git a/control-plane/subcommand/inject-connect/command.go b/control-plane/subcommand/inject-connect/command.go index 1bf22c78a9..71e6473297 100644 --- a/control-plane/subcommand/inject-connect/command.go +++ b/control-plane/subcommand/inject-connect/command.go @@ -102,6 +102,9 @@ type Command struct { flagDefaultEnableTransparentProxy bool flagTransparentProxyDefaultOverwriteProbes bool + // CNI flag. + flagEnableCNI bool + // Peering flags. flagEnablePeering bool @@ -178,6 +181,8 @@ func (c *Command) init() { "discovery across Consul namespaces. Only necessary if ACLs are enabled.") c.flagSet.BoolVar(&c.flagDefaultEnableTransparentProxy, "default-enable-transparent-proxy", true, "Enable transparent proxy mode for all Consul service mesh applications by default.") + c.flagSet.BoolVar(&c.flagEnableCNI, "enable-cni", false, + "Enable CNI traffic redirection for all Consul service mesh applications.") c.flagSet.BoolVar(&c.flagTransparentProxyDefaultOverwriteProbes, "transparent-proxy-default-overwrite-probes", true, "Overwrite Kubernetes probes to point to Envoy by default when in Transparent Proxy mode.") c.flagSet.BoolVar(&c.flagEnableConsulDNS, "enable-consul-dns", false, @@ -516,6 +521,7 @@ func (c *Command) Run(args []string) int { K8SNSMirroringPrefix: c.flagK8SNSMirroringPrefix, CrossNamespaceACLPolicy: c.flagCrossNamespaceACLPolicy, EnableTransparentProxy: c.flagDefaultEnableTransparentProxy, + EnableCNI: c.flagEnableCNI, TProxyOverwriteProbes: c.flagTransparentProxyDefaultOverwriteProbes, EnableConsulDNS: c.flagEnableConsulDNS, ResourcePrefix: c.flagResourcePrefix, diff --git a/control-plane/subcommand/install-cni/binary.go b/control-plane/subcommand/install-cni/binary.go new file mode 100644 index 0000000000..472c8bece7 --- /dev/null +++ b/control-plane/subcommand/install-cni/binary.go @@ -0,0 +1,56 @@ +package installcni + +import ( + "fmt" + "os" + "path/filepath" +) + +// copyFile copies a file from a source directory to a destination directory. +func copyFile(srcFile, destDir string) error { + // If the src file does not exist then either the incorrect command line argument was used or + // the docker container we built is broken somehow. + if _, err := os.Stat(srcFile); os.IsNotExist(err) { + return err + } + + filename := filepath.Base(srcFile) + // If the destDir does not exist then the incorrect command line argument was used or + // the CNI settings for the kubelet are not correct. + info, err := os.Stat(destDir) + if os.IsNotExist(err) { + return err + } + + if !info.IsDir() { + return fmt.Errorf("destination directory %s is not a directory", destDir) + } + + // Check if the user bit is enabled in file permission. + if info.Mode().Perm()&(1<<(uint(7))) == 0 { + return fmt.Errorf("cannot write to destination directory %s", destDir) + } + + srcBytes, err := os.ReadFile(srcFile) + if err != nil { + return fmt.Errorf("could not read %s file", srcFile) + } + + err = os.WriteFile(filepath.Join(destDir, filename), srcBytes, info.Mode()) + if err != nil { + return fmt.Errorf("error copying %s binary to %s", filename, destDir) + } + return nil +} + +func removeFile(path string) error { + if _, err := os.Stat(path); os.IsNotExist(err) { + // Nothing to delete. + return nil + } + + if err := os.Remove(path); err != nil { + return fmt.Errorf("error removing file %s: %w", path, err) + } + return nil +} diff --git a/control-plane/subcommand/install-cni/binary_test.go b/control-plane/subcommand/install-cni/binary_test.go new file mode 100644 index 0000000000..e65f61c63b --- /dev/null +++ b/control-plane/subcommand/install-cni/binary_test.go @@ -0,0 +1,146 @@ +package installcni + +import ( + "fmt" + "os" + "path/filepath" + "syscall" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestCopyFile(t *testing.T) { + t.Parallel() + cases := []struct { + name string + srcFile func() string // use any file + dir func() string + expectedErr func(string, string) error + }{ + { + name: "source file does not exist", + srcFile: func() string { + return "doesnotexist" + }, + dir: func() string { + return "" + }, + expectedErr: func(srcFile, _ string) error { + return &os.PathError{Op: "stat", Path: srcFile, Err: syscall.ENOENT} + }, + }, + { + name: "destination directory does not exist", + srcFile: func() string { + return "testdata/10-kindnet.conflist" // any file will do + }, + dir: func() string { + return "" + }, + expectedErr: func(_, destDir string) error { + return &os.PathError{Op: "stat", Path: destDir, Err: syscall.ENOENT} + }, + }, + { + name: "destination is not a directory", + srcFile: func() string { + return "testdata/10-kindnet.conflist" // any file wil do + }, + dir: func() string { + return "testdata/10-kindnet.conflist" + }, + + expectedErr: func(_, destDir string) error { + return fmt.Errorf("destination directory %s is not a directory", destDir) + }, + }, + { + name: "destination directory does not have write permissions", + srcFile: func() string { + return "testdata/10-kindnet.conflist" + }, // any file wil do + dir: func() string { + tempDir := t.TempDir() + os.Chmod(tempDir, 0555) + return tempDir + }, + expectedErr: func(_, destDir string) error { + return fmt.Errorf("cannot write to destination directory %s", destDir) + }, + }, + { + name: "cannot read source file", + srcFile: func() string { + tempDir := t.TempDir() + err := copyFile("testdata/10-kindnet.conflist", tempDir) + require.NoError(t, err) + filepath := filepath.Join(tempDir, "10-kindnet.conflist") + os.Chmod(filepath, 0111) + return filepath + }, + dir: func() string { + tempDir := t.TempDir() + return tempDir + }, + expectedErr: func(srcFile, _ string) error { + return fmt.Errorf("could not read %s file", srcFile) + }, + }, + { + name: "copy file to dest directory", + srcFile: func() string { + return "testdata/10-kindnet.conflist" + }, + dir: func() string { + tempDir := t.TempDir() + return tempDir + }, + expectedErr: func(_, _ string) error { + return nil + }, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + destDir := c.dir() + srcFile := c.srcFile() + actualErr := copyFile(srcFile, destDir) + + expErr := c.expectedErr(srcFile, destDir) + + require.Equal(t, expErr, actualErr) + }) + } +} + +func TestRemoveFile(t *testing.T) { + t.Parallel() + cases := []struct { + name string + srcFile func() string // use any file + }{ + { + name: "source file does not exist, nothing to remove, no error", + srcFile: func() string { + return "doesnotexist" + }, + }, + { + name: "can remove file", + srcFile: func() string { + tempDir := t.TempDir() + err := copyFile("testdata/10-kindnet.conflist", tempDir) + require.NoError(t, err) + filepath := filepath.Join(tempDir, "10-kindnet.conflist") + return filepath + }, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + err := removeFile(c.srcFile()) + require.NoError(t, err) + }) + } +} diff --git a/control-plane/subcommand/install-cni/cniconfig.go b/control-plane/subcommand/install-cni/cniconfig.go new file mode 100644 index 0000000000..2c40bcda36 --- /dev/null +++ b/control-plane/subcommand/install-cni/cniconfig.go @@ -0,0 +1,274 @@ +package installcni + +import ( + "encoding/json" + "fmt" + "os" + "sort" + "strings" + + "github.com/containernetworking/cni/libcni" + "github.com/google/go-cmp/cmp" + "github.com/hashicorp/consul-k8s/control-plane/cni/config" + "github.com/mitchellh/mapstructure" +) + +// defaultCNIConfigFile gets the the correct config file from the cni net dir. +// Adapted from kubelet: https://github.com/kubernetes/kubernetes/blob/954996e231074dc7429f7be1256a579bedd8344c/pkg/kubelet/dockershim/network/cni/cni.go#L134. +func defaultCNIConfigFile(dir string) (string, error) { + files, err := libcni.ConfFiles(dir, []string{".conf", ".conflist", ".json"}) + if err != nil { + return "", fmt.Errorf("error while trying to find files in %s: %w", dir, err) + } + + // No config files have shown up yet and it is ok to run this function again. + if len(files) == 0 { + return "", nil + } + + sort.Strings(files) + for _, confFile := range files { + var confList *libcni.NetworkConfigList + if strings.HasSuffix(confFile, ".conflist") { + confList, err = libcni.ConfListFromFile(confFile) + if err != nil { + // Error loading CNI config list file. + continue + } + } else { + conf, err := libcni.ConfFromFile(confFile) + if err != nil { + // Error loading CNI config file. + continue + } + // Ensure the config has a "type" so we know what plugin to run. + // Also catches the case where somebody put a conflist into a conf file. + if conf.Network.Type == "" { + // Error loading CNI config file: no 'type'. + continue + } + + confList, err = libcni.ConfListFromConf(conf) + if err != nil { + // Error converting CNI config file to list. + continue + } + } + if len(confList.Plugins) == 0 { + // CNI config list has no networks, skipping". + continue + } + + return confFile, nil + } + // There were files but none of them were valid + return "", fmt.Errorf("no valid config files found in %s", dir) +} + +// The format of the main cni config file is unstructured json consisting of a header and list of plugins +// +// { +// "cniVersion": "0.3.1", +// "name": "kindnet", +// "plugins": [ +// { +// +// }, +// { +// +// } +// ] +// } +// appendCNIConfig appends the consul-cni configuration to the main configuration file. +func appendCNIConfig(consulCfg *config.CNIConfig, cfgFile string) error { + // Read the config file and convert it to a map. + cfgMap, err := configFileToMap(cfgFile) + if err != nil { + return fmt.Errorf("could not convert config file to map: %w", err) + } + + // Get the 'plugins' map embedded inside of the exisingMap. + plugins, err := pluginsFromMap(cfgMap) + if err != nil { + return err + } + + // Check to see if 'type: consul-cni' already exists and remove it before appending. + // This can happen in a CrashLoop and we prevents many duplicate entries in the config file. + for i, p := range plugins { + plugin, ok := p.(map[string]interface{}) + if !ok { + return fmt.Errorf("error reading plugin from plugin list") + } + if plugin["type"] == consulCNIName { + plugins = append(plugins[:i], plugins[i+1:]...) + break + } + } + + // Take the consul cni config object and convert it to a map so that we can use it with the other maps. + consulMap, err := consulMapFromConfig(consulCfg) + if err != nil { + return fmt.Errorf("error converting consul config into map: %w", err) + } + + // Append the consul-cni map to the already existing plugins. + cfgMap["plugins"] = append(plugins, consulMap) + + // Marshal into a new json object + cfgJSON, err := json.MarshalIndent(cfgMap, "", " ") + if err != nil { + return fmt.Errorf("error marshalling existing CNI config: %w", err) + } + + // Libcni nuance/bug. If the newline is missing, the cni plugin will throw errors saying that it cannot get parse the config. + cfgJSON = append(cfgJSON, "\n"...) + + // Write the file out. + err = os.WriteFile(cfgFile, cfgJSON, os.FileMode(0o644)) + if err != nil { + return fmt.Errorf("error writing config file %s: %w", cfgFile, err) + } + return nil +} + +// configFileToMap takes an unstructure JSON config file and converts it into a map. +func configFileToMap(cfgFile string) (map[string]interface{}, error) { + if _, err := os.Stat(cfgFile); os.IsNotExist(err) { + return nil, fmt.Errorf("config file %s does not exist: %w", cfgFile, err) + } + + // Read the main config file. + cfgBytes, err := os.ReadFile(cfgFile) + if err != nil { + return nil, fmt.Errorf("could not read file %s: %w", cfgFile, err) + } + + // Convert the json config file into a map. The map that is created has 2 parts: + // [0] the cni header + // [1] the plugins + var cfgMap map[string]interface{} + err = json.Unmarshal(cfgBytes, &cfgMap) + if err != nil { + return nil, fmt.Errorf("error unmarshalling existing config file %s: %w", cfgFile, err) + } + return cfgMap, nil +} + +// pluginsFromMap takes an unmarshalled config JSON map, return the plugin list asserted as a []interface{}. +func pluginsFromMap(cfgMap map[string]interface{}) ([]interface{}, error) { + plugins, ok := cfgMap["plugins"].([]interface{}) + if !ok { + return nil, fmt.Errorf("error getting plugins from config map") + } + return plugins, nil +} + +// consulMapFromConfig converts the consul CNI config into a map. +func consulMapFromConfig(consulCfg *config.CNIConfig) (map[string]interface{}, error) { + var consulMap map[string]interface{} + err := mapstructure.Decode(consulCfg, &consulMap) + if err != nil { + return nil, fmt.Errorf("error decoding consul config into a map: %w", err) + } + return consulMap, nil +} + +// removeCNIConfig removes the consul-cni config from the CNI config file. Used as part of cleanup. +func removeCNIConfig(cfgFile string) error { + // Read the config file and convert it to a map. + cfgMap, err := configFileToMap(cfgFile) + if err != nil { + return fmt.Errorf("could not convert config file to map: %w", err) + } + + // Get the 'plugins' map embedded inside of the exisingMap. + plugins, err := pluginsFromMap(cfgMap) + if err != nil { + return err + } + + // Find the 'consul-cni' plugin and remove it. + for i, p := range plugins { + // We do not unmarshall this into a map[string]map[string]interface{} because there is no structure to + // the plugins. They are unstructured json and can be in any format that the plugin provider wishes. + plugin, ok := p.(map[string]interface{}) + if !ok { + return fmt.Errorf("error reading plugin from plugin list") + } + if plugin["type"] == consulCNIName { + cfgMap["plugins"] = append(plugins[:i], plugins[i+1:]...) + break + } + } + + // Marshal into a new json file. + cfgJSON, err := json.MarshalIndent(cfgMap, "", " ") + if err != nil { + return fmt.Errorf("error marshalling existing CNI config: %w", err) + } + + cfgJSON = append(cfgJSON, "\n"...) + + // Write the file out. + err = os.WriteFile(cfgFile, cfgJSON, os.FileMode(0o644)) + if err != nil { + return fmt.Errorf("error writing config file %s: %w", cfgFile, err) + } + return nil +} + +// validConfig validates that the consul-cni config exists in the config file and it is valid. It should be the +// last plugin in the plugin chain. +func validConfig(cfg *config.CNIConfig, cfgFile string) error { + // Convert the config file into a map. + cfgMap, err := configFileToMap(cfgFile) + if err != nil { + return fmt.Errorf("could not convert config file to map: %w", err) + } + + // Get the 'plugins' map embedded inside of the exisingMap. + plugins, err := pluginsFromMap(cfgMap) + if err != nil { + return err + } + + // Create an empty config so that we can populate it if found. + existingCfg := &config.CNIConfig{} + // Find the 'consul-cni' plugin in the list of plugins. + found := false + num_plugins := len(plugins) + for i, p := range plugins { + plugin, ok := p.(map[string]interface{}) + if !ok { + return fmt.Errorf("error reading plugin from plugin list") + } + if plugin["type"] == consulCNIName { + // Populate existingCfg with the consul-cni plugin info so that we can compare it with what + // is expected. + err := mapstructure.Decode(plugin, &existingCfg) + if err != nil { + return fmt.Errorf("error decoding consul config into a map: %w", err) + } + found = true + // Check to see that consul-cni plugin is the last plugin in the chain. + if !(num_plugins-1 == i) { + return fmt.Errorf("consul-cni config is not the last plugin in plugin chain") + } + break + } + } + + if !found { + return fmt.Errorf("consul-cni config missing from config file") + } + + // Compare the config that is passed to the installer to what is in the config file. There could be a + // difference if the config was corrupted or during a helm update or upgrade. + equal := cmp.Equal(existingCfg, cfg) + if !equal { + return fmt.Errorf("consul-cni config has changed") + } + + return nil +} diff --git a/control-plane/subcommand/install-cni/cniconfig_test.go b/control-plane/subcommand/install-cni/cniconfig_test.go new file mode 100644 index 0000000000..961d59cba6 --- /dev/null +++ b/control-plane/subcommand/install-cni/cniconfig_test.go @@ -0,0 +1,336 @@ +package installcni + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "testing" + + "github.com/hashicorp/consul-k8s/control-plane/cni/config" + "github.com/stretchr/testify/require" +) + +// TODO: Add more tests for different types of CNI plugins we may encounter on GKE/AWS/EKS + +// TestDefaultCNIConfigFile_NoFiles tests an edge case in defaultCNIConfigFile where it returns "" when there are no +// config files in the directory. +func TestDefaultCNIConfigFile_NoFiles(t *testing.T) { + cfgFile := "" + tempDir := t.TempDir() + + actual, err := defaultCNIConfigFile(tempDir) + require.Equal(t, cfgFile, actual) + require.Equal(t, nil, err) +} + +// TestDefaultCNIConfigFile tests finding the correct config file in the cniNetDir directory. +func TestDefaultCNIConfigFile(t *testing.T) { + cases := []struct { + name string + cfgFile string + dir func(string) string + expectedErr error + }{ + { + name: "valid .conflist file found", + cfgFile: "testdata/10-kindnet.conflist", + dir: func(cfgFile string) string { + tempDir := t.TempDir() + err := copyFile(cfgFile, tempDir) + if err != nil { + t.Fatal(err) + } + return tempDir + }, + expectedErr: nil, + }, + { + name: "several files, should choose .conflist file", + cfgFile: "testdata/10-kindnet.conflist", + dir: func(cfgFile string) string { + tempDir := t.TempDir() + err := copyFile(cfgFile, tempDir) + if err != nil { + t.Fatal(err) + } + err = copyFile("testdata/10-fake-cni.conf", tempDir) + if err != nil { + t.Fatal(err) + } + + return tempDir + }, + expectedErr: nil, + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + tempDir := c.dir(c.cfgFile) + actual, err := defaultCNIConfigFile(tempDir) + + filename := filepath.Base(c.cfgFile) + filepath := filepath.Join(tempDir, filename) + require.Equal(t, filepath, actual) + require.Equal(t, c.expectedErr, err) + }) + } +} + +// TestCreateCNIConfigFile tests the writing of the config file. +func TestAppendCNIConfig(t *testing.T) { + cases := []struct { + name string + consulConfig *config.CNIConfig + // source config file that we would expect to see in /opt/cni/net.d + cfgFile string + // golden file that our output should look like + goldenFile string + }{ + { + name: "valid kindnet file", + consulConfig: config.NewDefaultCNIConfig(), + cfgFile: "testdata/10-kindnet.conflist", + goldenFile: "testdata/10-kindnet.conflist.golden", + }, + { + name: "invalid kindnet file that already has consul-cni config inserted, should remove entry and append", + consulConfig: config.NewDefaultCNIConfig(), + cfgFile: "testdata/10-kindnet.conflist.alreadyinserted", + goldenFile: "testdata/10-kindnet.conflist.golden", + }, + { + name: "valid calico file", + consulConfig: &config.CNIConfig{ + Name: config.DefaultPluginName, + Type: config.DefaultPluginType, + CNIBinDir: config.DefaultCNIBinDir, + CNINetDir: config.DefaultCNINetDir, + Kubeconfig: config.DefaultKubeconfig, + LogLevel: config.DefaultLogLevel, + Multus: config.DefaultMultus, + }, + cfgFile: "testdata/10-calico.conflist", + goldenFile: "testdata/10-calico.conflist.golden", + }, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + // Copy the config file to a temporary location so that we can append to it. + tempDir := t.TempDir() + err := copyFile(c.cfgFile, tempDir) + require.NoError(t, err) + + // Get the config file name in the tempdir. + filename := filepath.Base(c.cfgFile) + tempDestFile := filepath.Join(tempDir, filename) + + err = appendCNIConfig(c.consulConfig, tempDestFile) + require.NoError(t, err) + + actual, err := ioutil.ReadFile(tempDestFile) + require.NoError(t, err) + + expected, err := ioutil.ReadFile(c.goldenFile) + require.NoError(t, err) + + require.Equal(t, string(expected), string(actual)) + }) + } +} + +// TestConfigFileToMap test configFileToMap which takes an unstructure JSON config file and converts it into a map. +func TestConfigFileToMap(t *testing.T) { + cfgFile := "testdata/10-tiny.conflist" + + expectedMap := map[string]interface{}{ + "cniVersion": "0.3.1", + "name": "k8s-pod-network", + "plugins": []interface{}{ + map[string]interface{}{ + "type": "calico", + }, + map[string]interface{}{ + "type": "bandwidth", + }, + }, + } + + tempDir := t.TempDir() + err := copyFile(cfgFile, tempDir) + require.NoError(t, err) + + filename := filepath.Base(cfgFile) + tempDestFile := filepath.Join(tempDir, filename) + + actualMap, err := configFileToMap(tempDestFile) + require.NoError(t, err) + require.Equal(t, expectedMap, actualMap) +} + +// TestPluginsFromMap tests pluginsFromMap which takes an unmarshalled config JSON map, return the plugin list asserted +// as a []interface{}. +func TestPluginsFromMap(t *testing.T) { + cfgMap := map[string]interface{}{ + "cniVersion": "0.3.1", + "name": "k8s-pod-network", + "plugins": []interface{}{ + map[string]interface{}{ + "type": "calico", + }, + map[string]interface{}{ + "type": "bandwidth", + }, + }, + } + + expectedPlugins := []interface{}{ + map[string]interface{}{ + "type": "calico", + }, + map[string]interface{}{ + "type": "bandwidth", + }, + } + + actualPlugins, err := pluginsFromMap(cfgMap) + require.NoError(t, err) + require.Equal(t, expectedPlugins, actualPlugins) +} + +func TestConsulMapFromConfig(t *testing.T) { + consulConfig := &config.CNIConfig{ + Name: config.DefaultPluginName, + Type: config.DefaultPluginType, + CNIBinDir: config.DefaultCNIBinDir, + CNINetDir: config.DefaultCNINetDir, + Kubeconfig: config.DefaultKubeconfig, + LogLevel: config.DefaultLogLevel, + Multus: config.DefaultMultus, + } + + expectedMap := map[string]interface{}{ + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": consulCNIName, + "type": consulCNIName, + } + + actualMap, err := consulMapFromConfig(consulConfig) + require.NoError(t, err) + require.Equal(t, expectedMap, actualMap) +} + +// TestRemoveCNIConfig tests the writing of the config file. +// Doing the opposite of the TestAppendCNIConfig test. We start with a proper golden file and should +// end up with an empty cfg file. +func TestRemoveCNIConfig(t *testing.T) { + cases := []struct { + name string + cfgFile string + goldenFile string + }{ + { + name: "remove cni config from populated kindnet file", + cfgFile: "testdata/10-kindnet.conflist", + goldenFile: "testdata/10-kindnet.conflist.golden", + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + // copy the config file to a temporary location so that we can append to it + tempDir := t.TempDir() + err := copyFile(c.goldenFile, tempDir) + if err != nil { + t.Fatal(err) + } + + // get the config file name in the tempdir + filename := filepath.Base(c.goldenFile) + tempDestFile := filepath.Join(tempDir, filename) + + err = removeCNIConfig(tempDestFile) + if err != nil { + t.Fatal(err) + } + + actual, err := ioutil.ReadFile(tempDestFile) + require.NoError(t, err) + + expected, err := ioutil.ReadFile(c.cfgFile) + require.NoError(t, err) + + require.Equal(t, string(expected), string(actual)) + }) + } +} + +// TestValidConfig tests validating the config file. +func TestValidConfig(t *testing.T) { + cases := []struct { + name string + cfgFile string + consulConfig *config.CNIConfig + expectedErr error + }{ + { + name: "config is missing from file", + cfgFile: "testdata/10-kindnet.conflist", + consulConfig: &config.CNIConfig{}, + expectedErr: fmt.Errorf("consul-cni config missing from config file"), + }, + { + name: "config passed to installer does not match config in config file", + cfgFile: "testdata/10-kindnet.conflist.golden", + consulConfig: &config.CNIConfig{}, + expectedErr: fmt.Errorf("consul-cni config has changed"), + }, + { + name: "config passed to installer does not match config in config file", + cfgFile: "testdata/10-kindnet.conflist.golden", + consulConfig: &config.CNIConfig{ + CNIBinDir: "foo", + CNINetDir: "bar", + }, + expectedErr: fmt.Errorf("consul-cni config has changed"), + }, + { + name: "config passed matches config in config file", + cfgFile: "testdata/10-kindnet.conflist.golden", + consulConfig: &config.CNIConfig{ + CNIBinDir: "/opt/cni/bin", + CNINetDir: "/etc/cni/net.d", + Kubeconfig: "ZZZ-consul-cni-kubeconfig", + LogLevel: "info", + Multus: false, + Name: "consul-cni", + Type: "consul-cni", + }, + expectedErr: nil, + }, + { + name: "config is corrupted and consul-cni is not last in chain", + cfgFile: "testdata/10-kindnet.conflist.notlast", + consulConfig: &config.CNIConfig{ + CNIBinDir: "/opt/cni/bin", + CNINetDir: "/etc/cni/net.d", + Kubeconfig: "ZZZ-consul-cni-kubeconfig", + LogLevel: "info", + Multus: false, + Name: "consul-cni", + Type: "consul-cni", + }, + expectedErr: fmt.Errorf("consul-cni config is not the last plugin in plugin chain"), + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + actualErr := validConfig(c.consulConfig, c.cfgFile) + require.Equal(t, c.expectedErr, actualErr) + }) + } +} diff --git a/control-plane/subcommand/install-cni/command.go b/control-plane/subcommand/install-cni/command.go new file mode 100644 index 0000000000..22c1acdf84 --- /dev/null +++ b/control-plane/subcommand/install-cni/command.go @@ -0,0 +1,281 @@ +package installcni + +import ( + "context" + "flag" + "fmt" + "os" + "os/signal" + "path/filepath" + "sync" + "syscall" + + "github.com/fsnotify/fsnotify" + "github.com/hashicorp/consul-k8s/control-plane/cni/config" + "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" + "github.com/hashicorp/consul-k8s/control-plane/subcommand/flags" + "github.com/hashicorp/go-hclog" + "github.com/mitchellh/cli" +) + +const ( + defaultCNIBinSourceDir = "/bin" + consulCNIName = "consul-cni" // Name of the plugin and binary. They must be the same as per the CNI spec. + defaultLogJSON = false +) + +// Command flags and structure. +type Command struct { + UI cli.Ui + + // flagCNIBinDir is the location on the host of the consul-cni binary. + flagCNIBinDir string + // flagCNINetDir is the location on the host of cni configuration. + flagCNINetDir string + // flagCNIBinSourceDir is the location of consul-cni binary inside the installer container (/bin). + flagCNIBinSourceDir string + // flageKubeconfig is the filename of the generated kubeconfig that the plugin will use to communicate with + // the kubernetes api. + flagKubeconfig string + // flagLogLevel is the logging level. + flagLogLevel string + // flagLogJson is a boolean flag for json logging format. + flagLogJSON bool + // flagMultus is a boolean flag for multus support. + flagMultus bool + + flagSet *flag.FlagSet + + once sync.Once + help string + logger hclog.Logger + sigCh chan os.Signal +} + +func (c *Command) init() { + c.flagSet = flag.NewFlagSet("", flag.ContinueOnError) + c.flagSet.StringVar(&c.flagCNIBinDir, "cni-bin-dir", config.DefaultCNIBinDir, "Location of CNI plugin binaries.") + c.flagSet.StringVar(&c.flagCNINetDir, "cni-net-dir", config.DefaultCNINetDir, "Location to write the CNI plugin configuration.") + c.flagSet.StringVar(&c.flagCNIBinSourceDir, "bin-source-dir", defaultCNIBinSourceDir, "Host location to copy the binary from") + c.flagSet.StringVar(&c.flagKubeconfig, "kubeconfig", config.DefaultKubeconfig, "Name of the kubernetes config file") + c.flagSet.StringVar(&c.flagLogLevel, "log-level", config.DefaultLogLevel, + "Log verbosity level. Supported values (in order of detail) are \"trace\", "+ + "\"debug\", \"info\", \"warn\", and \"error\".") + c.flagSet.BoolVar(&c.flagLogJSON, "log-json", defaultLogJSON, "Enable or disable JSON output format for logging.") + c.flagSet.BoolVar(&c.flagMultus, "multus", config.DefaultMultus, "If the plugin is a multus plugin (default = false)") + + c.help = flags.Usage(help, c.flagSet) + + // Wait on an interrupt or terminate to exit. This channel must be initialized before + // Run() is called so that there are no race conditions where the channel + // is not defined. + if c.sigCh == nil { + c.sigCh = make(chan os.Signal, 1) + signal.Notify(c.sigCh, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) + } +} + +// Run runs the command. +func (c *Command) Run(args []string) int { + c.once.Do(c.init) + + if err := c.flagSet.Parse(args); err != nil { + return 1 + } + + // Set up logging. + if c.logger == nil { + var err error + c.logger, err = common.Logger(c.flagLogLevel, c.flagLogJSON) + if err != nil { + c.UI.Error(err.Error()) + return 1 + } + } + + // Create the CNI Config from command flags. + cfg := &config.CNIConfig{ + Name: config.DefaultPluginName, + Type: config.DefaultPluginType, + CNIBinDir: c.flagCNIBinDir, + CNINetDir: c.flagCNINetDir, + Kubeconfig: c.flagKubeconfig, + LogLevel: c.flagLogLevel, + Multus: c.flagMultus, + } + + c.logger.Info("Running CNI install with configuration", + "name", cfg.Name, + "type", cfg.Type, + "cni_bin_dir", cfg.CNIBinDir, + "cni_net_dir", cfg.CNINetDir, + "multus", cfg.Multus, + "kubeconfig", cfg.Kubeconfig, + "log_level", cfg.LogLevel) + + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // Generate the kubeconfig file that will be used by the plugin to communicate with the kubernetes api. + c.logger.Debug("Creating kubeconfig", "file", cfg.Kubeconfig) + err := createKubeConfig(cfg.CNINetDir, cfg.Kubeconfig) + if err != nil { + c.logger.Error("could not create kube config", "error", err) + return 1 + } + + // Copy the consul-cni binary from the installer container to the host. + c.logger.Debug("Copying consul-cni binary", "destination", cfg.CNIBinDir) + srcFile := filepath.Join(c.flagCNIBinSourceDir, consulCNIName) + err = copyFile(srcFile, cfg.CNIBinDir) + if err != nil { + c.logger.Error("could not copy consul-cni binary", "error", err) + return 1 + } + + // Get the config file that is on the host. + c.logger.Debug("Getting default config file from", "destination", cfg.CNINetDir) + cfgFile, err := defaultCNIConfigFile(cfg.CNINetDir) + if err != nil { + c.logger.Error("could not get default CNI config file", "error", err) + return 1 + } + + // The config file does not exist and it probably means that the consul-cni plugin was installed or scheduled + // before other cni plugins on the node. We will add a directory watcher and wait for another plugin to + // be installed. + if cfgFile == "" { + c.logger.Info("CNI config file not found. Consul-cni is a chained plugin and another plugin must be installed first. Waiting...", "directory", cfg.CNINetDir) + } else { + // Check if there is valid config in the config file. It is invalid if no consul-cni config exists, + // the consul-cni config is not the last in the plugin chain or the consul-cni config is different from + // what is passed into helm (it could happen in a helm upgrade). + err := validConfig(cfg, cfgFile) + if err != nil { + // The invalid config is not critical and we can recover from it. + c.logger.Info("Installing plugin", "reason", err) + err = appendCNIConfig(cfg, cfgFile) + if err != nil { + c.logger.Error("could not append configuration to config file", "error", err) + return 1 + } + } + } + + // Watch for changes in the cniNetDir directory and fix/install the config file if need be. + err = c.directoryWatcher(ctx, cfg, cfg.CNINetDir, cfgFile) + if err != nil { + c.logger.Error("error with directory watcher", "error", err) + return 1 + } + return 0 +} + +// cleanup removes the consul-cni configuration and kubeconfig file from cniNetDir and cniBinDir. +func (c *Command) cleanup(cfg *config.CNIConfig, cfgFile string) { + var err error + c.logger.Info("Shutdown received, cleaning up") + if cfgFile != "" { + err = removeCNIConfig(cfgFile) + if err != nil { + c.logger.Error("Unable to cleanup CNI Config: %w", err) + } + } + + kubeconfig := filepath.Join(cfg.CNINetDir, cfg.Kubeconfig) + err = removeFile(kubeconfig) + if err != nil { + c.logger.Error("Unable to remove %s file: %w", kubeconfig, err) + } +} + +// directoryWatcher watches for changes in the cniNetDir forever. We watch the directory because there is a case where +// the installer could be the first cni plugin installed and we need to wait for another plugin to show up. Once +// installed we watch for changes, verify that our plugin installation is valid and re-install the consul-cni config. +func (c *Command) directoryWatcher(ctx context.Context, cfg *config.CNIConfig, dir, cfgFile string) error { + watcher, err := fsnotify.NewWatcher() + if err != nil { + return fmt.Errorf("could not create watcher: %w", err) + } + + c.logger.Info("Creating directory watcher for", "directory", dir) + err = watcher.Add(dir) + if err != nil { + return fmt.Errorf("could not watch %s directory: %w", dir, err) + } + //} + + // Cannot do "_ = defer watcher.Close()". + defer func() { + _ = watcher.Close() + }() + + for { + select { + case event, ok := <-watcher.Events: + if !ok { + c.logger.Error("Event watcher event is not ok", "event", event) + } + // For every event, get the config file, validate it and append the CNI configuration. If no + // config file is available, do nothing. This can happen if the consul-cni daemonset was + // created before other CNI plugins were installed. + if event.Op&(fsnotify.Create|fsnotify.Write|fsnotify.Remove) != 0 { + c.logger.Info("Modified event", "event", event) + // Always get the config file that is on the host as we do not know if it was deleted + // or not. + cfgFile, err = defaultCNIConfigFile(dir) + if err != nil { + c.logger.Error("Unable get default config file", "error", err) + break + } + if cfgFile != "" { + c.logger.Info("Using config file", "file", cfgFile) + + err = validConfig(cfg, cfgFile) + if err != nil { + // The invalid config is not critical and we can recover from it. + c.logger.Info("Installing plugin", "reason", err) + err = appendCNIConfig(cfg, cfgFile) + if err != nil { + c.logger.Error("Unable to install consul-cni config", "error", err) + return err + } + } else { + c.logger.Info("Valid config file detected, nothing to do") + break + } + } + + } + case err, ok := <-watcher.Errors: + if !ok { + c.logger.Error("Event watcher event is not ok", "error", err) + } + case <-ctx.Done(): + c.cleanup(cfg, cfgFile) + return nil + case <-c.sigCh: + c.cleanup(cfg, cfgFile) + return nil + } + } +} + +// Synopsis returns the summary of the cni install command. +func (c *Command) Synopsis() string { return synopsis } + +// Help returns the help output of the command. +func (c *Command) Help() string { + c.once.Do(c.init) + return c.help +} + +const ( + synopsis = "Consul CNI plugin installer" + help = ` +Usage: consul-k8s-control-plane cni-install [options] + + Install Consul CNI plugin + Not intended for stand-alone use. +` +) diff --git a/control-plane/subcommand/install-cni/command_test.go b/control-plane/subcommand/install-cni/command_test.go new file mode 100644 index 0000000000..a7e97a4aa9 --- /dev/null +++ b/control-plane/subcommand/install-cni/command_test.go @@ -0,0 +1,139 @@ +package installcni + +import ( + "context" + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + "time" + + "github.com/hashicorp/consul-k8s/control-plane/cni/config" + "github.com/hashicorp/consul-k8s/control-plane/subcommand/common" + "github.com/hashicorp/serf/testutil/retry" + "github.com/mitchellh/cli" + "github.com/stretchr/testify/require" +) + +func TestRun_FlagDefaults(t *testing.T) { + cmd := Command{} + cmd.init() + + require.Equal(t, cmd.flagCNIBinDir, config.DefaultCNIBinDir) + require.Equal(t, cmd.flagCNINetDir, config.DefaultCNINetDir) + require.Equal(t, cmd.flagCNIBinSourceDir, defaultCNIBinSourceDir) + require.Equal(t, cmd.flagKubeconfig, config.DefaultKubeconfig) + require.Equal(t, cmd.flagLogLevel, config.DefaultLogLevel) + require.Equal(t, cmd.flagLogJSON, defaultLogJSON) + require.Equal(t, cmd.flagMultus, config.DefaultMultus) +} + +func TestRun_DirectoryWatcher(t *testing.T) { + // Create a default configuration that matches golden file. + + consulConfig := config.NewDefaultCNIConfig() + configFile := "10-kindnet.conflist" + baseConfigFile := "testdata/10-kindnet.conflist" + goldenFile := "testdata/10-kindnet.conflist.golden" + notLastConfigFile := "testdata/10-kindnet.conflist.notlast" + + // Create a Command and context. + var err error + ctx, cancel := context.WithCancel(context.Background()) + t.Cleanup(cancel) + tempDir := t.TempDir() + + // Setup the Command. + ui := cli.NewMockUi() + cmd := &Command{ + UI: ui, + } + cmd.init() + cmd.logger, err = common.Logger("info", false) + require.NoError(t, err) + + // Create the file watcher. + go func() { + err := cmd.directoryWatcher(ctx, consulConfig, tempDir, "") + require.NoError(t, err) + }() + time.Sleep(50 * time.Millisecond) + + t.Log("File event 1: Copy a base config file that does not contain the consul entry. Should detect and add consul-cni") + err = copyFile(baseConfigFile, tempDir) + require.NoError(t, err) + time.Sleep(50 * time.Millisecond) + // The golden file contains the consul config. + expected, err := ioutil.ReadFile(goldenFile) + require.NoError(t, err) + // Get the name of the config file in the tempDir and read it. + tempDestFile := filepath.Join(tempDir, configFile) + actual, err := ioutil.ReadFile(tempDestFile) + require.NoError(t, err) + // Filewatcher should have detected a change and appended to the config file. Make sure + // files match. + retry.Run(t, func(r *retry.R) { + require.Equal(r, string(expected), string(actual)) + }) + + t.Log("File event 2: config file changed and consul-cni is not last in the plugin list. Should detect and fix.") + err = replaceFile(notLastConfigFile, filepath.Join(tempDir, configFile)) + require.NoError(t, err) + time.Sleep(50 * time.Millisecond) + // Re-read the config file so we can compare the updated config file. + actual, err = ioutil.ReadFile(tempDestFile) + require.NoError(t, err) + // Filewatcher should have detected change, fixed and appended to the config file. Make sure + // files match. + retry.Run(t, func(r *retry.R) { + require.Equal(r, string(expected), string(actual)) + }) + + t.Log("File event 3: consul config was removed from the config file. Should detect and fix.") + err = replaceFile(baseConfigFile, filepath.Join(tempDir, configFile)) + require.NoError(t, err) + // Filewatcher should have detected change, fixed and appended to the config file. Make sure + // files match. + retry.Run(t, func(r *retry.R) { + require.Equal(r, string(expected), string(actual)) + }) + + // If we exit the test too quickly it can cause a race condition where File event 3 is still running and we + // delete the config file while the test is doing a write. + time.Sleep(50 * time.Millisecond) +} + +func replaceFile(srcFile, destFile string) error { + if _, err := os.Stat(srcFile); os.IsNotExist(err) { + return fmt.Errorf("source %s file does not exist: %v", srcFile, err) + } + + filename := filepath.Base(destFile) + destDir := filepath.Dir(destFile) + + info, err := os.Stat(destDir) + if os.IsNotExist(err) { + return fmt.Errorf("destination directory %s does not exist: %v", destDir, err) + } + + if !info.IsDir() { + return fmt.Errorf("destination directory %s is not a directory: %v", destDir, err) + } + + // Check if the user bit is enabled in file permission. + if info.Mode().Perm()&(1<<(uint(7))) == 0 { + return fmt.Errorf("cannot write to destination directory %s: %v", destDir, err) + } + + srcBytes, err := os.ReadFile(srcFile) + if err != nil { + return fmt.Errorf("could not read %s file: %v", srcFile, err) + } + + err = os.WriteFile(filepath.Join(destDir, filename), srcBytes, info.Mode()) + if err != nil { + return fmt.Errorf("error copying %s file to %s: %v", filename, destDir, err) + } + return nil +} diff --git a/control-plane/subcommand/install-cni/kubeconfig.go b/control-plane/subcommand/install-cni/kubeconfig.go new file mode 100644 index 0000000000..e611828e36 --- /dev/null +++ b/control-plane/subcommand/install-cni/kubeconfig.go @@ -0,0 +1,128 @@ +package installcni + +import ( + "errors" + "fmt" + "io/ioutil" + "os" + "path/filepath" + + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" +) + +const ( + // Default location of the service account token on a kubernetes host. + defaultTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token" +) + +// createKubeConfig creates the kubeconfig file that the consul-cni plugin will use to communicate with the +// kubernetes API. +func createKubeConfig(cniNetDir, kubeconfigFile string) error { + var restCfg *rest.Config + + // TODO: Move clientset out of this method and put it in 'Run' + + // Get kube config information from cluster. + restCfg, err := rest.InClusterConfig() + if err != nil { + return err + } + err = rest.LoadTLSFiles(restCfg) + if err != nil { + return err + } + + server, err := kubernetesServer() + if err != nil { + return err + } + + token, err := serviceAccountToken(defaultTokenPath) + if err != nil { + return err + } + + data, err := kubeConfigYaml(server, token, restCfg.CAData) + if err != nil { + return err + } + + // Write the kubeconfig file to the host. + destFile := filepath.Join(cniNetDir, kubeconfigFile) + err = os.WriteFile(destFile, data, os.FileMode(0o644)) + if err != nil { + return fmt.Errorf("error writing kube config file %s: %w", destFile, err) + } + + return nil +} + +// kubeConfigYaml creates the kubeconfig in yaml format using kubectl packages. +func kubeConfigYaml(server, token string, certificateAuthorityData []byte) ([]byte, error) { + // Use the same struct that kubectl uses to create the kubeconfig file. + kubeconfig := clientcmdapi.Config{ + APIVersion: "v1", + Kind: "Config", + Clusters: map[string]*clientcmdapi.Cluster{ + "local": { + Server: server, + CertificateAuthorityData: certificateAuthorityData, + }, + }, + AuthInfos: map[string]*clientcmdapi.AuthInfo{ + "consul-cni": { + Token: token, + }, + }, + Contexts: map[string]*clientcmdapi.Context{ + "consul-cni-context": { + Cluster: "local", + AuthInfo: "consul-cni", + }, + }, + CurrentContext: "consul-cni-context", + } + + // Create yaml from the kubeconfig using the yaml writer from kubectl. + data, err := clientcmd.Write(kubeconfig) + if err != nil { + return nil, fmt.Errorf("error creating kubeconfig yaml: %w", err) + } + return data, nil +} + +// kubernetesServer gets the protocol, host and port from the server environment. +func kubernetesServer() (string, error) { + protocol, ok := os.LookupEnv("KUBERNETES_SERVICE_PROTOCOL") + if !ok { + protocol = "https" + } + + host, ok := os.LookupEnv("KUBERNETES_SERVICE_HOST") + if !ok { + return "", fmt.Errorf("Unable to get kubernetes api server host from environment") + } + + port, ok := os.LookupEnv("KUBERNETES_SERVICE_PORT") + if !ok { + return "", fmt.Errorf("Unable to get kubernetes api server port from environment") + } + + // Server string format is https://[127.0.0.1]:443. The [] are what other plugins are using in their kubeconfig. + server := fmt.Sprintf("%s://[%s]:%s", protocol, host, port) + return server, nil +} + +// serviceAccountToken gets the service token from a directory on the host. +func serviceAccountToken(tokenPath string) (string, error) { + if _, err := os.Stat(tokenPath); errors.Is(err, os.ErrNotExist) { + return "", fmt.Errorf("tokenPath does not exist: %w", err) + } + token, err := ioutil.ReadFile(tokenPath) + if err != nil { + return "", fmt.Errorf("could not read service account token: %w", err) + } + return string(token), nil +} diff --git a/control-plane/subcommand/install-cni/kubeconfig_test.go b/control-plane/subcommand/install-cni/kubeconfig_test.go new file mode 100644 index 0000000000..22a7eae9b1 --- /dev/null +++ b/control-plane/subcommand/install-cni/kubeconfig_test.go @@ -0,0 +1,48 @@ +package installcni + +import ( + "io/ioutil" + "path/filepath" + "testing" + + "github.com/stretchr/testify/require" +) + +// TestKubeConfigYaml generates a kubeconfig yaml file and compares it against a golden file +// Note: This test can fail if the version of client-go/kubernetes changes. The kubectl Config struct sometimes +// inserts a `as-user-extra: null` into the yaml it generates depending on the version. When this happen, the golden +// file needs to be updated. v0.22.2 does not have as-user-extra, while v0.24.2 does. +func TestKubeConfigYaml(t *testing.T) { + cases := []struct { + name string + server string + token string + certificateAuthorityData []byte + goldenFile string // Golden file that our output should look like. + }{ + { + name: "valid kubeconfig file", + server: "https://[172.30.0.1]:443", + token: "eyJhbGciOiJSUzI1NiIsImtp", + certificateAuthorityData: []byte("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0"), + goldenFile: "ZZZ-consul-cni-kubeconfig.golden", + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + actual, err := kubeConfigYaml(c.server, c.token, c.certificateAuthorityData) + if err != nil { + t.Fatal(err) + } + + require.NoError(t, err) + + golden := filepath.Join("testdata", c.goldenFile) + expected, err := ioutil.ReadFile(golden) + require.NoError(t, err) + + require.Equal(t, string(expected), string(actual)) + }) + } +} diff --git a/control-plane/subcommand/install-cni/testdata/10-calico.conflist b/control-plane/subcommand/install-cni/testdata/10-calico.conflist new file mode 100644 index 0000000000..00cb446532 --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-calico.conflist @@ -0,0 +1,30 @@ +{ + "name": "k8s-pod-network", + "cniVersion": "0.3.1", + "plugins": [ + { + "type": "calico", + "datastore_type": "kubernetes", + "mtu": 0, + "nodename_file_optional": false, + "log_level": "Info", + "log_file_path": "/var/log/calico/cni/cni.log", + "ipam": { "type": "calico-ipam", "assign_ipv4" : "true", "assign_ipv6" : "false"}, + "container_settings": { + "allow_ip_forwarding": false + }, + "policy": { + "type": "k8s" + }, + "kubernetes": { + "k8s_api_root":"https://10.96.0.1:443", + "kubeconfig": "/etc/cni/net.d/calico-kubeconfig" + } + }, + { + "type": "bandwidth", + "capabilities": {"bandwidth": true} + }, + {"type": "portmap", "snat": true, "capabilities": {"portMappings": true}} + ] +} \ No newline at end of file diff --git a/control-plane/subcommand/install-cni/testdata/10-calico.conflist.golden b/control-plane/subcommand/install-cni/testdata/10-calico.conflist.golden new file mode 100644 index 0000000000..6544355cb1 --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-calico.conflist.golden @@ -0,0 +1,51 @@ +{ + "cniVersion": "0.3.1", + "name": "k8s-pod-network", + "plugins": [ + { + "container_settings": { + "allow_ip_forwarding": false + }, + "datastore_type": "kubernetes", + "ipam": { + "assign_ipv4": "true", + "assign_ipv6": "false", + "type": "calico-ipam" + }, + "kubernetes": { + "k8s_api_root": "https://10.96.0.1:443", + "kubeconfig": "/etc/cni/net.d/calico-kubeconfig" + }, + "log_file_path": "/var/log/calico/cni/cni.log", + "log_level": "Info", + "mtu": 0, + "nodename_file_optional": false, + "policy": { + "type": "k8s" + }, + "type": "calico" + }, + { + "capabilities": { + "bandwidth": true + }, + "type": "bandwidth" + }, + { + "capabilities": { + "portMappings": true + }, + "snat": true, + "type": "portmap" + }, + { + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/10-fake-cni.conf b/control-plane/subcommand/install-cni/testdata/10-fake-cni.conf new file mode 100644 index 0000000000..28986f5c5f --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-fake-cni.conf @@ -0,0 +1,7 @@ +{ + "cniVersion": "0.4.0", + "type": "fake-cni", + "log_level": "info", + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", +} diff --git a/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist new file mode 100644 index 0000000000..0ae728093c --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist @@ -0,0 +1,33 @@ +{ + "cniVersion": "0.3.1", + "name": "kindnet", + "plugins": [ + { + "ipMasq": false, + "ipam": { + "dataDir": "/run/cni-ipam-state", + "ranges": [ + [ + { + "subnet": "10.244.0.0/24" + } + ] + ], + "routes": [ + { + "dst": "0.0.0.0/0" + } + ], + "type": "host-local" + }, + "mtu": 1500, + "type": "ptp" + }, + { + "capabilities": { + "portMappings": true + }, + "type": "portmap" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.alreadyinserted b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.alreadyinserted new file mode 100644 index 0000000000..3c108d766b --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.alreadyinserted @@ -0,0 +1,42 @@ +{ + "cniVersion": "0.3.1", + "name": "kindnet", + "plugins": [ + { + "ipMasq": false, + "ipam": { + "dataDir": "/run/cni-ipam-state", + "ranges": [ + [ + { + "subnet": "10.244.0.0/24" + } + ] + ], + "routes": [ + { + "dst": "0.0.0.0/0" + } + ], + "type": "host-local" + }, + "mtu": 1500, + "type": "ptp" + }, + { + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" + }, + { + "capabilities": { + "portMappings": true + }, + "type": "portmap" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.golden b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.golden new file mode 100644 index 0000000000..15a65be4a3 --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.golden @@ -0,0 +1,42 @@ +{ + "cniVersion": "0.3.1", + "name": "kindnet", + "plugins": [ + { + "ipMasq": false, + "ipam": { + "dataDir": "/run/cni-ipam-state", + "ranges": [ + [ + { + "subnet": "10.244.0.0/24" + } + ] + ], + "routes": [ + { + "dst": "0.0.0.0/0" + } + ], + "type": "host-local" + }, + "mtu": 1500, + "type": "ptp" + }, + { + "capabilities": { + "portMappings": true + }, + "type": "portmap" + }, + { + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.notlast b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.notlast new file mode 100644 index 0000000000..3c108d766b --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-kindnet.conflist.notlast @@ -0,0 +1,42 @@ +{ + "cniVersion": "0.3.1", + "name": "kindnet", + "plugins": [ + { + "ipMasq": false, + "ipam": { + "dataDir": "/run/cni-ipam-state", + "ranges": [ + [ + { + "subnet": "10.244.0.0/24" + } + ] + ], + "routes": [ + { + "dst": "0.0.0.0/0" + } + ], + "type": "host-local" + }, + "mtu": 1500, + "type": "ptp" + }, + { + "cni_bin_dir": "/opt/cni/bin", + "cni_net_dir": "/etc/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" + }, + { + "capabilities": { + "portMappings": true + }, + "type": "portmap" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/10-tiny.conflist b/control-plane/subcommand/install-cni/testdata/10-tiny.conflist new file mode 100644 index 0000000000..0bea15c9b9 --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/10-tiny.conflist @@ -0,0 +1,12 @@ +{ + "name": "k8s-pod-network", + "cniVersion": "0.3.1", + "plugins": [ + { + "type": "calico" + }, + { + "type": "bandwidth" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/ZZZ-consul-cni-kubeconfig.golden b/control-plane/subcommand/install-cni/testdata/ZZZ-consul-cni-kubeconfig.golden new file mode 100644 index 0000000000..dcb29b3a2e --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/ZZZ-consul-cni-kubeconfig.golden @@ -0,0 +1,18 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: TFMwdExTMUNSVWRKVGlCRFJWSlVTVVpKUTBGVVJTMHRMUzA= + server: https://[172.30.0.1]:443 + name: local +contexts: +- context: + cluster: local + user: consul-cni + name: consul-cni-context +current-context: consul-cni-context +kind: Config +preferences: {} +users: +- name: consul-cni + user: + token: eyJhbGciOiJSUzI1NiIsImtp diff --git a/control-plane/subcommand/server-acl-init/command.go b/control-plane/subcommand/server-acl-init/command.go index af72f325c8..69a98a28d8 100644 --- a/control-plane/subcommand/server-acl-init/command.go +++ b/control-plane/subcommand/server-acl-init/command.go @@ -742,17 +742,17 @@ type gatewayRulesGenerator func(name, namespace string) (string, error) type ConfigureGatewayParams struct { // GatewayType specifies whether it is an ingress or terminating gateway. GatewayType string - //GatewayNames is the collection of gateways that have been specified. + // GatewayNames is the collection of gateways that have been specified. GatewayNames []string - //AuthMethodName is the authmethod for which to register the binding rules and policies for the gateways + // AuthMethodName is the authmethod for which to register the binding rules and policies for the gateways AuthMethodName string - //RuleGenerator is the function that supplies the rules that will be added to the policy. + // RuleGenerator is the function that supplies the rules that will be added to the policy. RulesGenerator gatewayRulesGenerator - //ConsulDC is the name of the DC where the gateways will be registered + // ConsulDC is the name of the DC where the gateways will be registered ConsulDC string - //PrimaryDC is the name of the Primary Data Center + // PrimaryDC is the name of the Primary Data Center PrimaryDC string - //Primary specifies whether the ConsulDC is the Primary Data Center + // Primary specifies whether the ConsulDC is the Primary Data Center Primary bool } @@ -954,7 +954,7 @@ func (c *Command) validateFlags() error { // For the Consul node name to be discoverable via DNS, it must contain only // dashes and alphanumeric characters. Length is also constrained. // These restrictions match those defined in Consul's agent definition. - var invalidDnsRe = regexp.MustCompile(`[^A-Za-z0-9\\-]+`) + invalidDnsRe := regexp.MustCompile(`[^A-Za-z0-9\\-]+`) const maxDNSLabelLength = 63 if invalidDnsRe.MatchString(c.flagSyncConsulNodeName) { From c703f82753aa1770c06eb296ee97c67e80eeb332 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Fri, 26 Aug 2022 12:17:16 -0500 Subject: [PATCH 104/235] Kubernetes 1.24 support (#1431) * Support for Kubernetes 1.21+ --- .circleci/config.yml | 4 +- CHANGELOG.md | 5 + README.md | 2 +- acceptance/framework/k8s/kubectl.go | 4 +- acceptance/framework/vault/vault_cluster.go | 30 +++- .../bases/multiport-app/kustomization.yaml | 1 + .../fixtures/bases/multiport-app/secret.yaml | 15 ++ .../tests/vault/vault_partitions_test.go | 14 +- acceptance/tests/vault/vault_wan_fed_test.go | 14 +- charts/consul/Chart.yaml | 2 +- .../consul/templates/auth-method-secret.yaml | 16 +++ .../templates/connect-inject-clusterrole.yaml | 3 +- .../consul/test/unit/auth-method-secret.bats | 20 +++ .../test/unit/connect-inject-clusterrole.bats | 5 +- control-plane/connect-inject/mesh_webhook.go | 17 ++- .../connect-inject/mesh_webhook_test.go | 130 +++++++++++++++++- .../server-acl-init/connect_inject.go | 30 ++-- .../server-acl-init/connect_inject_test.go | 39 ++++++ 18 files changed, 321 insertions(+), 30 deletions(-) create mode 100644 acceptance/tests/fixtures/bases/multiport-app/secret.yaml create mode 100644 charts/consul/templates/auth-method-secret.yaml create mode 100644 charts/consul/test/unit/auth-method-secret.bats diff --git a/.circleci/config.yml b/.circleci/config.yml index 613e308ff9..7743a5d811 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,7 +38,7 @@ commands: sudo tar -C /usr/local/bin -xzf gotestsum_1.6.4_linux_amd64.tar.gz rm gotestsum_1.6.4_linux_amd64.tar.gz - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.0/kind-linux-amd64 + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.14.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind @@ -506,7 +506,7 @@ jobs: - checkout - install-prereqs - create-kind-clusters: - version: "v1.22.4" + version: "v1.24.0" - restore_cache: keys: - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f34db1073..348df68af9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ IMPROVEMENTS: * Display a message when `proxy list` returns no results. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] +FEATURES: +* Kubernetes 1.24 + * Add support for Kubernetes 1.24 where ServiceAccounts no longer have long term JWT tokens. [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] + * Upgrade kubeVersion in helm chart to support Kubernetes 1.21+. + ## 0.47.1 (August 12, 2022) BUG FIXES: diff --git a/README.md b/README.md index de65faff15..fb09cb129c 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ use Consul with Kubernetes, please see the ### Prerequisites * **Helm 3.2+** (Helm 2 is not supported) - * **Kubernetes 1.19+** - This is the earliest version of Kubernetes tested. + * **Kubernetes 1.21+** - This is the earliest version of Kubernetes tested. It is possible that this chart works with earlier versions, but it is untested. diff --git a/acceptance/framework/k8s/kubectl.go b/acceptance/framework/k8s/kubectl.go index 7382cb0507..e766395f47 100644 --- a/acceptance/framework/k8s/kubectl.go +++ b/acceptance/framework/k8s/kubectl.go @@ -102,7 +102,9 @@ func KubectlDelete(t *testing.T, options *k8s.KubectlOptions, configPath string) // deletes it from the cluster by running 'kubectl delete -k'. // If there's an error deleting the file, fail the test. func KubectlDeleteK(t *testing.T, options *k8s.KubectlOptions, kustomizeDir string) { - _, err := RunKubectlAndGetOutputE(t, options, "delete", "--timeout=60s", "-k", kustomizeDir) + // Ignore not found errors because Kubernetes automatically cleans up the kube secrets that we deployed + // referencing the ServiceAccount when it is deleted. + _, err := RunKubectlAndGetOutputE(t, options, "delete", "--timeout=60s", "--ignore-not-found", "-k", kustomizeDir) require.NoError(t, err) } diff --git a/acceptance/framework/vault/vault_cluster.go b/acceptance/framework/vault/vault_cluster.go index aadbbf8fee..3710617fa7 100644 --- a/acceptance/framework/vault/vault_cluster.go +++ b/acceptance/framework/vault/vault_cluster.go @@ -149,6 +149,24 @@ func (v *VaultCluster) bootstrap(t *testing.T, vaultNamespace string) { namespace := v.helmOptions.KubectlOptions.Namespace vaultServerServiceAccountName := fmt.Sprintf("%s-vault", v.releaseName) + + // In Kube 1.24+ the serviceAccount does not have a secret automatically generated so we will create one prior to + // needing to use it in ConfigureAuthMethod. Vault expects the user to create the secret manually for any + // Kube AuthMethod use. + retry.Run(t, func(r *retry.R) { + sa, err := v.kubernetesClient.CoreV1().ServiceAccounts(namespace).Get(context.Background(), vaultServerServiceAccountName, metav1.GetOptions{}) + require.NoError(r, err) + if len(sa.Secrets) == 0 { + _, err = v.kubernetesClient.CoreV1().Secrets(namespace).Create(context.Background(), &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: vaultServerServiceAccountName, + Annotations: map[string]string{corev1.ServiceAccountNameKey: vaultServerServiceAccountName}, + }, + Type: corev1.SecretTypeServiceAccountToken, + }, metav1.CreateOptions{}) + require.NoError(t, err) + } + }) v.ConfigureAuthMethod(t, v.vaultClient, "kubernetes", "https://kubernetes.default.svc", vaultServerServiceAccountName, namespace) } @@ -163,18 +181,22 @@ func (v *VaultCluster) ConfigureAuthMethod(t *testing.T, vaultClient *vapi.Clien require.NoError(t, err) // To configure the auth method, we need to read the token and the CA cert from the auth method's - // service account token. + // service account token. In Kube-1.24 and above the secret is not automatically generated so we + // rely on it being created prior to calling ConfigureAuthMethod. // The JWT token and CA cert is what Vault server will use to validate service account token // with the Kubernetes API. + secretName := saName var sa *corev1.ServiceAccount retry.Run(t, func(r *retry.R) { sa, err = v.kubernetesClient.CoreV1().ServiceAccounts(saNS).Get(context.Background(), saName, metav1.GetOptions{}) require.NoError(r, err) - require.Len(r, sa.Secrets, 1) + // In Kubernetes <1.24 the serviceAccount will have a secret automatically generated. + if len(sa.Secrets) != 0 { + secretName = sa.Secrets[0].Name + } }) - v.logger.Logf(t, "updating vault kubernetes auth config for %s auth path", authPath) - tokenSecret, err := v.kubernetesClient.CoreV1().Secrets(saNS).Get(context.Background(), sa.Secrets[0].Name, metav1.GetOptions{}) + tokenSecret, err := v.kubernetesClient.CoreV1().Secrets(saNS).Get(context.Background(), secretName, metav1.GetOptions{}) require.NoError(t, err) _, err = vaultClient.Logical().Write(fmt.Sprintf("auth/%s/config", authPath), map[string]interface{}{ "token_reviewer_jwt": string(tokenSecret.Data["token"]), diff --git a/acceptance/tests/fixtures/bases/multiport-app/kustomization.yaml b/acceptance/tests/fixtures/bases/multiport-app/kustomization.yaml index b9d8e11f73..ead8b3afe5 100644 --- a/acceptance/tests/fixtures/bases/multiport-app/kustomization.yaml +++ b/acceptance/tests/fixtures/bases/multiport-app/kustomization.yaml @@ -1,6 +1,7 @@ resources: - deployment.yaml - service.yaml + - secret.yaml - serviceaccount.yaml - psp-rolebinding.yaml - anyuid-scc-rolebinding.yaml diff --git a/acceptance/tests/fixtures/bases/multiport-app/secret.yaml b/acceptance/tests/fixtures/bases/multiport-app/secret.yaml new file mode 100644 index 0000000000..cb3fa957e2 --- /dev/null +++ b/acceptance/tests/fixtures/bases/multiport-app/secret.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: + name: multiport-admin + annotations: + kubernetes.io/service-account.name: multiport-admin +type: kubernetes.io/service-account-token +--- +apiVersion: v1 +kind: Secret +metadata: + name: multiport + annotations: + kubernetes.io/service-account.name: multiport +type: kubernetes.io/service-account-token diff --git a/acceptance/tests/vault/vault_partitions_test.go b/acceptance/tests/vault/vault_partitions_test.go index 31eac7bc1a..5ff9ae7a6b 100644 --- a/acceptance/tests/vault/vault_partitions_test.go +++ b/acceptance/tests/vault/vault_partitions_test.go @@ -90,12 +90,24 @@ func TestVault_Partitions(t *testing.T) { require.NoError(t, err) // Create service account for the auth method in the secondary cluster. - _, err = clientClusterCtx.KubernetesClient(t).CoreV1().ServiceAccounts(ns).Create(context.Background(), &corev1.ServiceAccount{ + svcAcct, err := clientClusterCtx.KubernetesClient(t).CoreV1().ServiceAccounts(ns).Create(context.Background(), &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Name: authMethodRBACName, }, }, metav1.CreateOptions{}) require.NoError(t, err) + // In Kubernetes 1.24+ the serviceAccount does not automatically populate secrets with permanent JWT tokens, use this instead. + // It will be cleaned up by Kubernetes automatically since it references the ServiceAccount. + if len(svcAcct.Secrets) == 0 { + _, err = clientClusterCtx.KubernetesClient(t).CoreV1().Secrets(ns).Create(context.Background(), &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: authMethodRBACName, + Annotations: map[string]string{corev1.ServiceAccountNameKey: authMethodRBACName}, + }, + Type: corev1.SecretTypeServiceAccountToken, + }, metav1.CreateOptions{}) + require.NoError(t, err) + } t.Cleanup(func() { clientClusterCtx.KubernetesClient(t).RbacV1().ClusterRoleBindings().Delete(context.Background(), authMethodRBACName, metav1.DeleteOptions{}) clientClusterCtx.KubernetesClient(t).CoreV1().ServiceAccounts(ns).Delete(context.Background(), authMethodRBACName, metav1.DeleteOptions{}) diff --git a/acceptance/tests/vault/vault_wan_fed_test.go b/acceptance/tests/vault/vault_wan_fed_test.go index a58f45ee97..5e4a4acdc5 100644 --- a/acceptance/tests/vault/vault_wan_fed_test.go +++ b/acceptance/tests/vault/vault_wan_fed_test.go @@ -99,12 +99,24 @@ func TestVault_WANFederationViaGateways(t *testing.T) { require.NoError(t, err) // Create service account for the auth method in the secondary cluster. - _, err = secondaryCtx.KubernetesClient(t).CoreV1().ServiceAccounts(ns).Create(context.Background(), &corev1.ServiceAccount{ + svcAcct, err := secondaryCtx.KubernetesClient(t).CoreV1().ServiceAccounts(ns).Create(context.Background(), &corev1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ Name: authMethodRBACName, }, }, metav1.CreateOptions{}) require.NoError(t, err) + // In Kubernetes 1.24+ the serviceAccount does not automatically populate secrets with permanent JWT tokens, use this instead. + // It will be cleaned up by Kubernetes automatically since it references the ServiceAccount. + if len(svcAcct.Secrets) == 0 { + _, err = secondaryCtx.KubernetesClient(t).CoreV1().Secrets(ns).Create(context.Background(), &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: authMethodRBACName, + Annotations: map[string]string{corev1.ServiceAccountNameKey: authMethodRBACName}, + }, + Type: corev1.SecretTypeServiceAccountToken, + }, metav1.CreateOptions{}) + require.NoError(t, err) + } t.Cleanup(func() { secondaryCtx.KubernetesClient(t).RbacV1().ClusterRoleBindings().Delete(context.Background(), authMethodRBACName, metav1.DeleteOptions{}) secondaryCtx.KubernetesClient(t).CoreV1().ServiceAccounts(ns).Delete(context.Background(), authMethodRBACName, metav1.DeleteOptions{}) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 65fe2d2825..223400f17a 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -2,7 +2,7 @@ apiVersion: v2 name: consul version: 0.47.1 appVersion: 1.13.1 -kubeVersion: ">=1.19.0-0" +kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io icon: https://raw.githubusercontent.com/hashicorp/consul-k8s/main/assets/icon.png diff --git a/charts/consul/templates/auth-method-secret.yaml b/charts/consul/templates/auth-method-secret.yaml new file mode 100644 index 0000000000..af0aeb4e1b --- /dev/null +++ b/charts/consul/templates/auth-method-secret.yaml @@ -0,0 +1,16 @@ +{{- if .Values.global.acls.manageSystemACLs }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "consul.fullname" . }}-auth-method + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: auth-method + annotations: + kubernetes.io/service-account.name: {{ template "consul.fullname" . }}-auth-method +type: kubernetes.io/service-account-token +{{- end }} diff --git a/charts/consul/templates/connect-inject-clusterrole.yaml b/charts/consul/templates/connect-inject-clusterrole.yaml index afb485c227..a3f8822963 100644 --- a/charts/consul/templates/connect-inject-clusterrole.yaml +++ b/charts/consul/templates/connect-inject-clusterrole.yaml @@ -13,8 +13,7 @@ metadata: rules: {{- if .Values.global.acls.manageSystemACLs }} - apiGroups: [ "" ] - resources: - - serviceaccounts + resources: ["serviceaccounts", "secrets"] verbs: - get {{- end }} diff --git a/charts/consul/test/unit/auth-method-secret.bats b/charts/consul/test/unit/auth-method-secret.bats new file mode 100644 index 0000000000..134bc4f1cb --- /dev/null +++ b/charts/consul/test/unit/auth-method-secret.bats @@ -0,0 +1,20 @@ +#!/usr/bin/env bats + +load _helpers + +@test "auth-method/Secret disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/auth-method-secret.yaml \ + . +} + +@test "auth-method/Secret: enabled with global.acls.manageSystemACLs true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/auth-method-secret.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -s 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} diff --git a/charts/consul/test/unit/connect-inject-clusterrole.bats b/charts/consul/test/unit/connect-inject-clusterrole.bats index 39687badef..d9dd5933ca 100644 --- a/charts/consul/test/unit/connect-inject-clusterrole.bats +++ b/charts/consul/test/unit/connect-inject-clusterrole.bats @@ -125,7 +125,7 @@ load _helpers [ "${actual}" != null ] } -@test "connectInject/ClusterRole: sets get access to serviceaccounts when manageSystemACLSis true" { +@test "connectInject/ClusterRole: sets get access to serviceaccounts and secrets when manageSystemACLSis true" { cd `chart_dir` local object=$(helm template \ -s templates/connect-inject-clusterrole.yaml \ @@ -139,6 +139,9 @@ load _helpers local actual=$(echo $object | yq -r '.resources[| index("serviceaccounts")' | tee /dev/stderr) [ "${actual}" != null ] + local actual=$(echo $object | yq -r '.resources[| index("secrets")' | tee /dev/stderr) + [ "${actual}" != null ] + local actual=$(echo $object | yq -r '.apiGroups[0]' | tee /dev/stderr) [ "${actual}" = "" ] diff --git a/control-plane/connect-inject/mesh_webhook.go b/control-plane/connect-inject/mesh_webhook.go index eef1187835..54c458af7f 100644 --- a/control-plane/connect-inject/mesh_webhook.go +++ b/control-plane/connect-inject/mesh_webhook.go @@ -295,22 +295,31 @@ func (w *MeshWebhook) Handle(ctx context.Context, req admission.Request) admissi w.Log.Info(fmt.Sprintf("service: %s", svc)) if w.AuthMethod != "" { if svc != "" && pod.Spec.ServiceAccountName != svc { + secretName := "" sa, err := w.Clientset.CoreV1().ServiceAccounts(req.Namespace).Get(ctx, svc, metav1.GetOptions{}) if err != nil { w.Log.Error(err, "couldn't get service accounts") return admission.Errored(http.StatusInternalServerError, err) } if len(sa.Secrets) == 0 { + // Check to see if there is a secret with the same name as the ServiceAccount for Kube-1.24+. w.Log.Info(fmt.Sprintf("service account %s has zero secrets exp at least 1", svc)) - return admission.Errored(http.StatusInternalServerError, fmt.Errorf("service account %s has zero secrets, expected at least one", svc)) + sec, err := w.Clientset.CoreV1().Secrets(req.Namespace).Get(ctx, svc, metav1.GetOptions{}) + if err != nil { + w.Log.Error(err, "couldn't get Secret associated with Service Account") + return admission.Errored(http.StatusInternalServerError, err) + } + secretName = sec.Name + w.Log.Info(fmt.Sprintf("fetched secret: %s", secretName)) + } else { + secretName = sa.Secrets[0].Name } - saSecret := sa.Secrets[0].Name - w.Log.Info("found service account, mounting service account secret to Pod", "serviceAccountName", sa.Name) + w.Log.Info("found service account, mounting service account secret to Pod", "serviceAccountName", secretName) pod.Spec.Volumes = append(pod.Spec.Volumes, corev1.Volume{ Name: fmt.Sprintf("%s-service-account", svc), VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: saSecret, + SecretName: secretName, }, }, }) diff --git a/control-plane/connect-inject/mesh_webhook_test.go b/control-plane/connect-inject/mesh_webhook_test.go index 0f21b6dca7..cc7a9011c6 100644 --- a/control-plane/connect-inject/mesh_webhook_test.go +++ b/control-plane/connect-inject/mesh_webhook_test.go @@ -738,13 +738,14 @@ func TestHandlerHandle(t *testing.T) { }, }, { - "multi port pod", + "multiport pod kube < 1.24 with AuthMethod, serviceaccount has secret ref", MeshWebhook{ Log: logrtest.TestLogger{T: t}, AllowK8sNamespacesSet: mapset.NewSetWith("*"), DenyK8sNamespacesSet: mapset.NewSet(), decoder: decoder, - Clientset: defaultTestClientWithNamespace(), + Clientset: testClientWithServiceAccountAndSecretRefs(), + AuthMethod: "k8s", }, admission.Request{ AdmissionRequest: admissionv1.AdmissionRequest{ @@ -753,7 +754,62 @@ func TestHandlerHandle(t *testing.T) { Spec: basicSpec, ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - annotationService: "web, web-admin", + annotationService: "web,web-admin", + }, + }, + }), + }, + }, + "", + []jsonpatch.Operation{ + { + Operation: "add", + Path: "/spec/volumes", + }, + { + Operation: "add", + Path: "/spec/initContainers", + }, + { + Operation: "add", + Path: "/spec/containers/1", + }, + { + Operation: "add", + Path: "/spec/containers/2", + }, + { + Operation: "add", + Path: "/metadata/annotations/" + escapeJSONPointer(keyInjectStatus), + }, + { + Operation: "add", + Path: "/metadata/annotations/" + escapeJSONPointer(annotationOriginalPod), + }, + { + Operation: "add", + Path: "/metadata/labels", + }, + }, + }, + { + "multiport pod kube 1.24 with AuthMethod, serviceaccount does not have secret ref", + MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + Clientset: testClientWithServiceAccountAndSecrets(), + AuthMethod: "k8s", + }, + admission.Request{ + AdmissionRequest: admissionv1.AdmissionRequest{ + Namespace: namespaces.DefaultNamespace, + Object: encodeRaw(t, &corev1.Pod{ + Spec: basicSpec, + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + annotationService: "web,web-admin", }, }, }), @@ -1929,6 +1985,74 @@ func defaultTestClientWithNamespace() kubernetes.Interface { return clientWithNamespace("default") } +func testClientWithServiceAccountAndSecretRefs() kubernetes.Interface { + ns := corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + } + sa1 := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "web-admin", + Namespace: "default", + }, + Secrets: []corev1.ObjectReference{ + { + Name: "web-admin", + }, + }, + } + sa2 := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "web", + Namespace: "default", + }, + Secrets: []corev1.ObjectReference{ + { + Name: "web", + }, + }, + } + return fake.NewSimpleClientset(&ns, &sa1, &sa2) +} + +func testClientWithServiceAccountAndSecrets() kubernetes.Interface { + ns := corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + } + sa1 := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "web-admin", + Namespace: "default", + }, + } + secret1 := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "web-admin", + Namespace: "default", + Annotations: map[string]string{corev1.ServiceAccountNameKey: "web-admin"}, + }, + Type: corev1.SecretTypeServiceAccountToken, + } + sa2 := corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "web", + Namespace: "default", + }, + } + secret2 := corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "web", + Annotations: map[string]string{corev1.ServiceAccountNameKey: "web"}, + Namespace: "default", + }, + Type: corev1.SecretTypeServiceAccountToken, + } + return fake.NewSimpleClientset(&ns, &sa1, &sa2, &secret1, &secret2) +} + func clientWithNamespace(name string) kubernetes.Interface { ns := corev1.Namespace{ ObjectMeta: metav1.ObjectMeta{ diff --git a/control-plane/subcommand/server-acl-init/connect_inject.go b/control-plane/subcommand/server-acl-init/connect_inject.go index 5112eee906..0160efd0a1 100644 --- a/control-plane/subcommand/server-acl-init/connect_inject.go +++ b/control-plane/subcommand/server-acl-init/connect_inject.go @@ -94,17 +94,28 @@ func (c *Command) createAuthMethodTmpl(authMethodName string, useNS bool) (api.A return api.ACLAuthMethod{}, err } - // ServiceAccounts always have a secret name. The secret - // contains the JWT token. - // Because there could be multiple secrets attached to the service account, - // we need pick the first one of type "kubernetes.io/service-account-token". var saSecret *apiv1.Secret - for _, secretRef := range authMethodServiceAccount.Secrets { + var secretNames []string + if len(authMethodServiceAccount.Secrets) == 0 { + // In Kube 1.24+ there is no automatically generated long term JWT token for a ServiceAccount. + // Furthermore, there is no reference to a Secret in the ServiceAccount. Instead we have deployed + // a Secret in Helm which references the ServiceAccount and contains a permanent JWT token. + secretNames = append(secretNames, c.withPrefix("auth-method")) + } else { + // ServiceAccounts always have a SecretRef in Kubernetes < 1.24. The Secret contains the JWT token. + for _, secretRef := range authMethodServiceAccount.Secrets { + secretNames = append(secretNames, secretRef.Name) + } + } + // Because there could be multiple secrets attached to the service account, + // we need pick the first one of type corev1.SecretTypeServiceAccountToken. + // We will fetch the Secrets regardless of whether we created the Secret or Kubernetes did automatically. + for _, secretName := range secretNames { var secret *apiv1.Secret - err = c.untilSucceeds(fmt.Sprintf("getting %s Secret", secretRef.Name), + err = c.untilSucceeds(fmt.Sprintf("getting %s Secret", secretName), func() error { var err error - secret, err = c.clientset.CoreV1().Secrets(c.flagK8sNamespace).Get(c.ctx, secretRef.Name, metav1.GetOptions{}) + secret, err = c.clientset.CoreV1().Secrets(c.flagK8sNamespace).Get(c.ctx, secretName, metav1.GetOptions{}) return err }) if secret != nil && secret.Type == apiv1.SecretTypeServiceAccountToken { @@ -115,8 +126,9 @@ func (c *Command) createAuthMethodTmpl(authMethodName string, useNS bool) (api.A if err != nil { return api.ACLAuthMethod{}, err } - // This is very unlikely to happen because Kubernetes ensure that there is always - // a secret of type ServiceAccountToken. + + // This is unlikely to happen since we now deploy the secret through Helm, but should catch any corner-cases + // where the secret is not deployed for some reason. if saSecret == nil { return api.ACLAuthMethod{}, fmt.Errorf("found no secret of type 'kubernetes.io/service-account-token' associated with the %s service account", serviceAccountName) diff --git a/control-plane/subcommand/server-acl-init/connect_inject_test.go b/control-plane/subcommand/server-acl-init/connect_inject_test.go index 959f02e178..e3166442af 100644 --- a/control-plane/subcommand/server-acl-init/connect_inject_test.go +++ b/control-plane/subcommand/server-acl-init/connect_inject_test.go @@ -67,3 +67,42 @@ func TestCommand_createAuthMethodTmpl_SecretNotFound(t *testing.T) { _, err = cmd.createAuthMethodTmpl("test", true) require.EqualError(t, err, "found no secret of type 'kubernetes.io/service-account-token' associated with the release-name-consul-auth-method service account") } + +// Test that createAuthMethodTmpl succeeds in the case where the serviceAccount exists but no secrets are automatically +// created by Kubernetes for it. This is the behaviour that is present in Kube-1.24+. +func TestCommand_createAuthMethodTmpl(t *testing.T) { + serviceAccountName := resourcePrefix + "-auth-method" + secretName := resourcePrefix + "-auth-method" + k8s := fake.NewSimpleClientset() + ctx := context.Background() + + // Create a service account that does not reference a secret. + _, err := k8s.CoreV1().ServiceAccounts(ns).Create(ctx, &v1.ServiceAccount{ObjectMeta: metav1.ObjectMeta{Name: serviceAccountName}}, metav1.CreateOptions{}) + require.NoError(t, err) + + // Create a secret that references the serviceaccount. + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretName, + Labels: map[string]string{common.CLILabelKey: common.CLILabelValue}, + Annotations: map[string]string{ + v1.ServiceAccountNameKey: serviceAccountName, + }, + }, + Data: map[string][]byte{}, + Type: v1.SecretTypeServiceAccountToken, + } + _, err = k8s.CoreV1().Secrets(ns).Create(ctx, secret, metav1.CreateOptions{}) + require.NoError(t, err) + + cmd := &Command{ + flagK8sNamespace: ns, + flagResourcePrefix: resourcePrefix, + clientset: k8s, + log: hclog.New(nil), + ctx: ctx, + } + + _, err = cmd.createAuthMethodTmpl("test", true) + require.NoError(t, err) +} From fd33b7be8b0287928296440f19f2a55d86e9b8d4 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Fri, 26 Aug 2022 17:09:18 -0500 Subject: [PATCH 105/235] update changelog for kube-1.24 (#1461) * update changelog --- CHANGELOG.md | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 348df68af9..fb3f1d0ad6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,36 @@ ## UNRELEASED + FEATURES: * MaxInboundConnections in service-defaults CRD * Add support for MaxInboundConnections on the Service Defaults CRD. [[GH-1437](https://github.com/hashicorp/consul-k8s/pull/1437)] * Consul CNI Plugin * CNI Plugin for Consul-k8s [[GH-1465](https://github.com/hashicorp/consul-k8s/pull/1456)] +* Kubernetes 1.24 Support + * Add support for Kubernetes 1.24 where ServiceAccounts no longer have long term JWT tokens. [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] + * Upgrade kubeVersion in helm chart to support Kubernetes 1.21+. + +BREAKING CHANGES: +* Kubernetes 1.24 Support + * Users deploying multiple services to the same Pod (multiport) on Kubernetes 1.24+ must also deploy a Kube Secret for each ServiceAccount associated with the Consul service. The name of the Secret must match the ServiceAccount name and be of type 'kubernetes.io/service-account-token' + +Example: +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: svc1 + annotations: + kubernetes.io/service-account.name: svc1 +type: kubernetes.io/service-account-token +--- +apiVersion: v1 +kind: Secret +metadata: + name: svc2 + annotations: + kubernetes.io/service-account.name: svc2 +type: kubernetes.io/service-account-token +``` IMPROVEMENTS: * CLI: @@ -11,10 +38,6 @@ IMPROVEMENTS: * Display a message when `proxy list` returns no results. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] -FEATURES: -* Kubernetes 1.24 - * Add support for Kubernetes 1.24 where ServiceAccounts no longer have long term JWT tokens. [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] - * Upgrade kubeVersion in helm chart to support Kubernetes 1.21+. ## 0.47.1 (August 12, 2022) From f4db28c9f7f86224d65cb41dbf715ca6d91cac18 Mon Sep 17 00:00:00 2001 From: David Yu Date: Fri, 26 Aug 2022 15:50:36 -0700 Subject: [PATCH 106/235] README.md: update K8s versions (#1459) * README.md: update versions --- README.md | 8 ++++---- charts/consul/README.md | 23 ++++++++++++----------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index fb09cb129c..35b3c4b762 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ The `consul-k8s-control-plane` binary includes first-class integrations between Consul and Kubernetes. The project encapsulates multiple use cases such as syncing -services, injecting Connect sidecars, and more. +services, injecting Consul sidecars, and more. The Kubernetes integrations with Consul are [documented directly on the Consul website](https://www.consul.io/docs/platform/k8s/index.html). @@ -30,8 +30,8 @@ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). ## Features - * [**Consul Service Mesh (Connect)**](https://www.consul.io/docs/k8s/connect): - Run Consul Service Mesh (aka Consul Connect) on Kubernetes. This feature + * [**Consul Service Mesh**](https://www.consul.io/docs/k8s/connect): + Run Consul Service Mesh on Kubernetes. This feature injects Envoy sidecars and registers your Pods with Consul. * [**Catalog Sync**](https://www.consul.io/docs/k8s/service-sync): @@ -67,7 +67,7 @@ use Consul with Kubernetes, please see the ### Prerequisites * **Helm 3.2+** (Helm 2 is not supported) - * **Kubernetes 1.21+** - This is the earliest version of Kubernetes tested. + * **Kubernetes 1.21-1.24** - This is the earliest version of Kubernetes tested. It is possible that this chart works with earlier versions, but it is untested. diff --git a/charts/consul/README.md b/charts/consul/README.md index 36e104bb15..ccc695151d 100644 --- a/charts/consul/README.md +++ b/charts/consul/README.md @@ -20,8 +20,8 @@ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). ## Features - * [**Consul Service Mesh (Connect)**](https://www.consul.io/docs/k8s/connect): - Run Consul Service Mesh (aka Consul Connect) on Kubernetes. This feature + * [**Consul Service Mesh**](https://www.consul.io/docs/k8s/connect): + Run Consul Service Mesh on Kubernetes. This feature injects Envoy sidecars and registers your Pods with Consul. * [**Catalog Sync**](https://www.consul.io/docs/k8s/service-sync): @@ -31,7 +31,7 @@ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). ### Prerequisites * **Helm 3.2+** (Helm 2 is not supported) - * **Kubernetes 1.19+** - This is the earliest version of Kubernetes tested. + * **Kubernetes 1.21-1.24** - This is the earliest version of Kubernetes tested. It is possible that this chart works with earlier versions but it is untested. @@ -40,22 +40,23 @@ by contacting us at [security@hashicorp.com](mailto:security@hashicorp.com). Detailed installation instructions for Consul on Kubernetes are found [here](https://www.consul.io/docs/k8s/installation/overview). 1. Add the HashiCorp Helm Repository: - - $ helm repo add hashicorp https://helm.releases.hashicorp.com - "hashicorp" has been added to your repositories + ``` bash + $ helm repo add hashicorp https://helm.releases.hashicorp.com + ``` 2. Ensure you have access to the Consul Helm chart and you see the latest chart version listed. If you have previously added the HashiCorp Helm repository, run `helm repo update`. - $ helm search repo hashicorp/consul - NAME CHART VERSION APP VERSION DESCRIPTION - hashicorp/consul 0.35.0 1.10.3 Official HashiCorp Consul Chart + ```bash + $ helm search repo hashicorp/consul + ``` 3. Now you're ready to install Consul! To install Consul with the default configuration using Helm 3.2 run the following command below. This will create a `consul` Kubernetes namespace if not already present, and install Consul on the dedicated namespace. - $ helm install consul hashicorp/consul --set global.name=consul --create-namespace -n consul - NAME: consul + ```bash + $ helm install consul hashicorp/consul --set global.name=consul --create-namespace -n consul + ``` Please see the many options supported in the `values.yaml` file. These are also fully documented directly on the From 7a3a1fdbfd48d0dadf233930a0342129439f64de Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Mon, 29 Aug 2022 16:06:49 -0400 Subject: [PATCH 107/235] Add CNI to CRT (#1458) * Get CNI building with CRT --- .github/workflows/build.yml | 43 +++++++++++++++++++++++++++++++++++++ control-plane/Dockerfile | 4 ++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f7ac1521ba..217741fa8a 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -90,6 +90,19 @@ jobs: - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane.exe" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "control-plane", pkg_name: "consul-k8s-control-plane", "bin_name": "consul-k8s-control-plane" } + # consul-cni + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "386", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "freebsd", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "solaris", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "386", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni.exe" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "windows", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni.exe" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "amd64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "darwin", goarch: "arm64", component: "control-plane/cni", pkg_name: "consul-cni", "bin_name": "consul-cni" } + fail-fast: true name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} ${{ matrix.component }} build @@ -207,6 +220,16 @@ jobs: version: ${{ needs.get-product-version.outputs.product-version }} steps: - uses: actions/checkout@v2 + - uses: actions/download-artifact@v3 + with: + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip + path: control-plane/dist/cni/linux/${{ matrix.arch }} + - name: extract consul-cni zip + env: + ZIP_LOCATION: control-plane/dist/cni/linux/${{ matrix.arch }} + run: | + cd "${ZIP_LOCATION}" + unzip -j *.zip - name: Docker Build (Action) uses: hashicorp/actions-docker-build@v1 with: @@ -241,6 +264,16 @@ jobs: version: ${{ needs.get-product-version.outputs.product-version }} steps: - uses: actions/checkout@v2 + - uses: actions/download-artifact@v3 + with: + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip + path: control-plane/dist/cni/linux/${{ matrix.arch }} + - name: extract consul-cni zip + env: + ZIP_LOCATION: control-plane/dist/cni/linux/${{ matrix.arch }} + run: | + cd "${ZIP_LOCATION}" + unzip -j *.zip - name: Copy LICENSE.md run: cp LICENSE.md ./control-plane @@ -273,6 +306,16 @@ jobs: version: ${{ needs.get-product-version.outputs.product-version }} steps: - uses: actions/checkout@v2 + - uses: actions/download-artifact@v3 + with: + name: consul-cni_${{ needs.get-product-version.outputs.product-version }}_linux_${{ matrix.arch }}.zip + path: control-plane/dist/cni/linux/${{ matrix.arch }} + - name: extract consul-cni zip + env: + ZIP_LOCATION: control-plane/dist/cni/linux/${{ matrix.arch }} + run: | + cd ${ZIP_LOCATION} + unzip -j *.zip - name: Copy LICENSE.md run: cp LICENSE.md ./control-plane diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 459b5f974d..802ec4fab2 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -95,7 +95,7 @@ RUN addgroup ${BIN_NAME} && \ adduser -S -G ${BIN_NAME} 100 COPY dist/${TARGETOS}/${TARGETARCH}/${BIN_NAME} /bin/ -COPY cni/dist/${TARGETOS}/${TARGETARCH}/${CNI_BIN_NAME} /bin/ +COPY dist/cni/${TARGETOS}/${TARGETARCH}/${CNI_BIN_NAME} /bin/ USER 100 CMD /bin/${BIN_NAME} @@ -156,7 +156,7 @@ RUN groupadd --gid 1000 ${BIN_NAME} && \ usermod -a -G root ${BIN_NAME} COPY dist/${TARGETOS}/${TARGETARCH}/${BIN_NAME} /bin/ -COPY cni/dist/${TARGETOS}/${TARGETARCH}/${CNI_BIN_NAME} /bin/ +COPY dist/cni/${TARGETOS}/${TARGETARCH}/${CNI_BIN_NAME} /bin/ USER 100 CMD /bin/${BIN_NAME} From f08238f16b4dc5ab797ca5414b8d5ff3cb07c76d Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Mon, 29 Aug 2022 17:10:18 -0400 Subject: [PATCH 108/235] api-gateway: configure ACL auth appropriately in secondary dc (#1462) * api-gateway: configure acl-auth-method appropriately for controller in secondary dc Co-Authored-By: Thomas Eckert * Add test coverage for secondary datacenter configuration * Add changelog entry * Improve changelog entry * Fulfill flag dependencies for bats test Co-authored-by: Thomas Eckert --- CHANGELOG.md | 3 ++ .../api-gateway-controller-deployment.yaml | 5 ++++ .../api-gateway-controller-deployment.bats | 30 +++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb3f1d0ad6..e61e20480c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,9 @@ IMPROVEMENTS: * Display a message when `proxy list` returns no results. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] +BUG FIXES: +* Helm + * API Gateway: Configure ACL auth for controller correctly when deployed in secondary datacenter with federation enabled [[GH-1462](https://github.com/hashicorp/consul-k8s/pull/1462)] ## 0.47.1 (August 12, 2022) diff --git a/charts/consul/templates/api-gateway-controller-deployment.yaml b/charts/consul/templates/api-gateway-controller-deployment.yaml index 5665a4fc93..b090cbcb7f 100644 --- a/charts/consul/templates/api-gateway-controller-deployment.yaml +++ b/charts/consul/templates/api-gateway-controller-deployment.yaml @@ -204,7 +204,12 @@ spec: - | consul-k8s-control-plane acl-init \ -component-name=api-gateway-controller \ + {{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter }} + -acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method-{{ .Values.global.datacenter }} \ + -primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \ + {{- else }} -acl-auth-method={{ template "consul.fullname" . }}-k8s-component-auth-method \ + {{- end }} {{- if .Values.global.adminPartitions.enabled }} -partition={{ .Values.global.adminPartitions.name }} \ {{- end }} diff --git a/charts/consul/test/unit/api-gateway-controller-deployment.bats b/charts/consul/test/unit/api-gateway-controller-deployment.bats index c7f9093d5c..51273c1b77 100755 --- a/charts/consul/test/unit/api-gateway-controller-deployment.bats +++ b/charts/consul/test/unit/api-gateway-controller-deployment.bats @@ -400,6 +400,36 @@ load _helpers [ "${actual}" = "true" ] } +@test "apiGateway/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command when federation enabled in non-primary datacenter" { + cd `chart_dir` + local object=$(helm template \ + -s templates/api-gateway-controller-deployment.yaml \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=foo' \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.tls.enableAutoEncrypt=true' \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.datacenter=dc2' \ + --set 'global.federation.enabled=true' \ + --set 'global.federation.primaryDatacenter=dc1' \ + . | tee /dev/stderr | + yq '.spec.template.spec.initContainers[] | select(.name == "api-gateway-controller-acl-init")' | tee /dev/stderr) + + local actual=$(echo $object | + yq -r '.command | any(contains("consul-k8s-control-plane acl-init"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq -r '.command | any(contains("-acl-auth-method=release-name-consul-k8s-component-auth-method-dc2"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq -r '.command | any(contains("-primary-datacenter=dc1"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + @test "apiGateway/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command and environment with tls enabled and autoencrypt enabled" { cd `chart_dir` local object=$(helm template \ From 05c1266d1211889b6c68722db510b8708c933cc5 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Tue, 30 Aug 2022 10:20:23 -0400 Subject: [PATCH 109/235] Fix Listener Filter bugs and cover more Envoy Listener Filter Types (#1442) * Extend timeout for port-forward * Resolve merge conflict on config fixture * Resolve merge conflicts on how listeners are displayed * Fix linting issue * Finish Ratelimit config * Unescape > * Add Changelog * Fix unit tests * Fix acceptance tests * Remove the named return parameter Co-authored-by: Ashwin Venkatesh --- CHANGELOG.md | 4 + .../tests/connect/connect_inject_test.go | 2 +- cli/cmd/proxy/read/command.go | 7 +- cli/cmd/proxy/read/command_test.go | 8 +- cli/cmd/proxy/read/config.go | 155 +++++++-- cli/cmd/proxy/read/config_test.go | 298 +++++++++++++++++- cli/cmd/proxy/read/envoy_types.go | 91 +++++- cli/common/portforward.go | 2 +- 8 files changed, 516 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e61e20480c..a1689aa193 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,10 +37,14 @@ IMPROVEMENTS: * Display clusters by their short names rather than FQDNs for the `proxy read` command. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a message when `proxy list` returns no results. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] + * Extend the timeout for `consul-k8s proxy read` to establish a connection from 5s to 10s. + * Expand the set of Envoy Listener Filters that may be parsed and output to the Listeners table. BUG FIXES: * Helm * API Gateway: Configure ACL auth for controller correctly when deployed in secondary datacenter with federation enabled [[GH-1462](https://github.com/hashicorp/consul-k8s/pull/1462)] +* CLI + * Fix issue where SNI filters for Terminating Gateways showed up as blank lines. ## 0.47.1 (August 12, 2022) diff --git a/acceptance/tests/connect/connect_inject_test.go b/acceptance/tests/connect/connect_inject_test.go index b57e188fdb..ec694b8a95 100644 --- a/acceptance/tests/connect/connect_inject_test.go +++ b/acceptance/tests/connect/connect_inject_test.go @@ -114,7 +114,7 @@ func TestConnectInject(t *testing.T) { // Static Client must have Static Server as a cluster and endpoint. if strings.Contains(podName, "static-client") { require.Regexp(r, "static-server.*static-server\\.default\\.dc1\\.internal.*EDS", output) - require.Regexp(r, ipv4RegEx+".*static-server.default.dc1.internal", output) + require.Regexp(r, ipv4RegEx+".*static-server", output) } } diff --git a/cli/cmd/proxy/read/command.go b/cli/cmd/proxy/read/command.go index 235a17f4a5..4123f70adb 100644 --- a/cli/cmd/proxy/read/command.go +++ b/cli/cmd/proxy/read/command.go @@ -413,12 +413,15 @@ func (c *ReadCommand) outputJSON(configs map[string]*EnvoyConfig) error { cfgs[name] = cfg } - out, err := json.MarshalIndent(cfgs, "", "\t") + escaped, err := json.MarshalIndent(cfgs, "", "\t") if err != nil { return err } - c.UI.Output(string(out)) + // Unescape `>` the cheap way. + out := strings.ReplaceAll(string(escaped), "\\u003e", ">") + + c.UI.Output(out) return nil } diff --git a/cli/cmd/proxy/read/command_test.go b/cli/cmd/proxy/read/command_test.go index 48f5aab6a2..9a6902ccae 100644 --- a/cli/cmd/proxy/read/command_test.go +++ b/cli/cmd/proxy/read/command_test.go @@ -80,10 +80,10 @@ func TestReadCommandOutput(t *testing.T) { "-listeners": {"==> Listeners \\(2\\)", "Name.*Address:Port.*Direction.*Filter Chain Match.*Filters.*Last Updated", - "public_listener.*192\\.168\\.69\\.179:20000.*INBOUND.*Any.*\\* to local_app/", - "outbound_listener.*127.0.0.1:15001.*OUTBOUND.*10\\.100\\.134\\.173/32, 240\\.0\\.0\\.3/32.*to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", - "10\\.100\\.31\\.2/32, 240\\.0\\.0\\.5/32.*to frontend\\.default\\.dc1\\.internal\\.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00\\.consul", - "Any.*to original-destination"}, + "public_listener.*192\\.168\\.69\\.179:20000.*INBOUND.*Any.*\\* -> local_app/", + "outbound_listener.*127.0.0.1:15001.*OUTBOUND.*10\\.100\\.134\\.173/32, 240\\.0\\.0\\.3/32.*TCP: -> client", + "10\\.100\\.31\\.2/32, 240\\.0\\.0\\.5/32.*TCP: -> frontend", + "Any.*TCP: -> original-destination"}, "-routes": {"==> Routes \\(1\\)", "Name.*Destination Cluster.*Last Updated", diff --git a/cli/cmd/proxy/read/config.go b/cli/cmd/proxy/read/config.go index a3ec904146..3c1a105c0e 100644 --- a/cli/cmd/proxy/read/config.go +++ b/cli/cmd/proxy/read/config.go @@ -303,7 +303,7 @@ func parseListeners(rawCfg map[string]interface{}) ([]Listener, error) { filterChain = append(filterChain, FilterChain{ FilterChainMatch: strings.Join(filterChainMatch, ", "), - Filters: formatFilters(chain), + Filters: formatFilters(chain.Filters), }) } @@ -396,45 +396,156 @@ func parseSecrets(rawCfg map[string]interface{}) ([]Secret, error) { return secrets, nil } -func formatFilters(filterChain filterChain) (filters []string) { +func formatFilters(filters []filter) []string { + formatted := []string{} + // Filters can have many custom configurations, each must be handled differently. - formatters := map[string]func(typedConfig) string{ + // [List of known extensions](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/listener/v3/listener_components.proto). + formatters := map[string]func(filter) string{ + "type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit": formatFilterConnectionLimit, + "type.googleapis.com/envoy.extensions.filters.network.direct_response.v3.Config": formatFilterDirectResponse, + "type.googleapis.com/envoy.extensions.filters.network.echo.v3.Echo": formatFilterEcho, + "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz": formatFilterExtAuthz, + "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager": formatFilterHTTPConnectionManager, + "type.googleapis.com/envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit": formatFilterLocalRatelimit, + "type.googleapis.com/envoy.extensions.filters.network.ratelimit.v3.RateLimit": formatFilterRatelimit, "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC": formatFilterRBAC, + "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster": formatFilterSniCluster, "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy": formatFilterTCPProxy, - "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager": formatFilterHTTPConnectionManager, } - for _, chainFilter := range filterChain.Filters { - if formatter, ok := formatters[chainFilter.TypedConfig.Type]; ok { - filters = append(filters, formatter(chainFilter.TypedConfig)) + for _, filter := range filters { + if formatter, ok := formatters[filter.TypedConfig.Type]; ok { + formatted = append(formatted, formatter(filter)) + } else { + formatted = append(formatted, fmt.Sprintf("Unknown filter: %s", filter.TypedConfig.Type)) } } - return + return formatted } -func formatFilterTCPProxy(config typedConfig) (filter string) { - return "to " + config.Cluster +func formatFilterConnectionLimit(config filter) string { + return fmt.Sprintf("Connection limit: %d max connections with %s delay", config.TypedConfig.MaxConnections, config.TypedConfig.Delay) } -func formatFilterRBAC(cfg typedConfig) (filter string) { - action := cfg.Rules.Action - for _, principal := range cfg.Rules.Policies.ConsulIntentions.Principals { - regex := principal.Authenticated.PrincipalName.SafeRegex.Regex - filter += fmt.Sprintf("%s %s", action, regex) +func formatFilterDirectResponse(config filter) string { + out := []string{"Direct response: ->"} + if file := config.TypedConfig.Response.Filename; file != "" { + out = append(out, fmt.Sprintf("file:%s", file)) + } + if inlineBytes := config.TypedConfig.Response.InlineBytes; len(inlineBytes) != 0 { + if len(inlineBytes) > 24 { + out = append(out, fmt.Sprintf("bytes:%s...", string(inlineBytes)[:24])) + } else { + out = append(out, fmt.Sprintf("bytes:%s", string(inlineBytes))) + } + } + if inlineString := config.TypedConfig.Response.InlineString; inlineString != "" { + if len(inlineString) > 24 { + out = append(out, fmt.Sprintf("string:%s...", inlineString[:24])) + } else { + out = append(out, fmt.Sprintf("string:%s", inlineString)) + } + } + if envVar := config.TypedConfig.Response.EnvironmentVariable; envVar != "" { + out = append(out, fmt.Sprintf("env:%s", envVar)) + } + + return strings.Join(out, " ") +} + +func formatFilterEcho(config filter) string { + return "Echo: upstream will respond with the data it receives." +} + +func formatFilterExtAuthz(config filter) string { + var upstream string + if config.TypedConfig.GrpcService.EnvoyGrpc.ClusterName != "" { + upstream = config.TypedConfig.GrpcService.EnvoyGrpc.ClusterName + } else if config.TypedConfig.GrpcService.GoogleGrpc.TargetUri != "" { + upstream = config.TypedConfig.GrpcService.GoogleGrpc.TargetUri + } else { + upstream = "No upstream configured." } - return + + return fmt.Sprintf("External authorization: %s", upstream) } -func formatFilterHTTPConnectionManager(cfg typedConfig) (filter string) { - for _, host := range cfg.RouteConfig.VirtualHosts { - filter += strings.Join(host.Domains, ", ") - filter += " to " +func formatFilterHTTPConnectionManager(config filter) string { + out := "HTTP: " + for _, host := range config.TypedConfig.RouteConfig.VirtualHosts { + out += strings.Join(host.Domains, ", ") + out += " -> " routes := "" for _, route := range host.Routes { routes += fmt.Sprintf("%s%s", route.Route.Cluster, route.Match.Prefix) } - filter += routes + out += routes + } + return out +} + +func formatFilterLocalRatelimit(config filter) string { + return fmt.Sprintf("Local rate limit: tokens: max %d per-fill %d, interval: %s", + config.TypedConfig.TokenBucket.MaxTokens, + config.TypedConfig.TokenBucket.TokensPerFill, + config.TypedConfig.TokenBucket.FillInterval) +} + +func formatFilterRatelimit(config filter) string { + out := "Rate limit: " + + if config.TypedConfig.Domain != "" { + out += config.TypedConfig.Domain + " " } - return + + // Rate limit using descriptors. + if len(config.TypedConfig.Descriptors) != 0 { + for _, descriptor := range config.TypedConfig.Descriptors { + for _, entry := range descriptor.Entries { + out += fmt.Sprintf("%s:%s ", entry.Key, entry.Value) + } + out += fmt.Sprintf("%d req per %s", descriptor.Limit.RequestsPerUnit, strings.ToLower(descriptor.Limit.Unit)) + } + } + + // Rate limit using an external Envoy gRPC service. + if config.TypedConfig.RateLimitService.GrpcService.EnvoyGrpc.ClusterName != "" { + out += fmt.Sprintf("using %s ", config.TypedConfig.RateLimitService.GrpcService.EnvoyGrpc.ClusterName) + } + + // Rate limit using an external Google gRPC service. + if config.TypedConfig.RateLimitService.GrpcService.GoogleGrpc.TargetUri != "" { + out += fmt.Sprintf("using %s ", config.TypedConfig.RateLimitService.GrpcService.GoogleGrpc.TargetUri) + } + + // Notify the user that failure to reach the rate limiting service will deny the caller. + if config.TypedConfig.FailureModeDeny { + out += "will deny if unreachable" + } + + return strings.Trim(out, " ") +} + +func formatFilterRBAC(config filter) string { + out := "RBAC: " + action := config.TypedConfig.Rules.Action + for _, principal := range config.TypedConfig.Rules.Policies.ConsulIntentions.Principals { + regex := principal.Authenticated.PrincipalName.SafeRegex.Regex + out += fmt.Sprintf("%s %s", action, regex) + } + return out +} + +func formatFilterSniCluster(config filter) string { + return "SNI: Upstream cluster name set by SNI field in TLS connection." +} + +func formatFilterTCPProxy(config filter) string { + if config.TypedConfig.Cluster == "" { + return "TCP: No upstream cluster configured." + } + + return "TCP: -> " + strings.Split(config.TypedConfig.Cluster, ".")[0] } diff --git a/cli/cmd/proxy/read/config_test.go b/cli/cmd/proxy/read/config_test.go index a32451a3c2..243523698f 100644 --- a/cli/cmd/proxy/read/config_test.go +++ b/cli/cmd/proxy/read/config_test.go @@ -82,6 +82,296 @@ func TestFetchConfig(t *testing.T) { require.Equal(t, testEnvoyConfig.Secrets, envoyConfig.Secrets) } +// There are many protobuf types for filter extensions. This test ensures +// that the different types are formatted correctly. +func TestFormatFilters(t *testing.T) { + cases := map[string]struct { + filter filter + expected string + }{ + "Connection Limit": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.connection_limit.v3.ConnectionLimit", + MaxConnections: 42, + Delay: "200s", + }, + }, + expected: "Connection limit: 42 max connections with 200s delay", + }, + "Direct Response with file": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.direct_response.v3.Config", + Response: filterResponse{ + Filename: "cat-photo.jpg", + }, + }, + }, + expected: "Direct response: -> file:cat-photo.jpg", + }, + "Direct Response with bytes": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.direct_response.v3.Config", + Response: filterResponse{ + InlineBytes: []byte("abcd"), + }, + }, + }, + expected: "Direct response: -> bytes:abcd", + }, + "Direct Response with lots of bytes": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.direct_response.v3.Config", + Response: filterResponse{ + InlineBytes: []byte("abcdefghijklmnopqrstuvwxyz"), + }, + }, + }, + expected: "Direct response: -> bytes:abcdefghijklmnopqrstuvwx...", + }, + "Direct Response with string": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.direct_response.v3.Config", + Response: filterResponse{ + InlineString: "efgh", + }, + }, + }, + expected: "Direct response: -> string:efgh", + }, + "Direct Response with long string": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.direct_response.v3.Config", + Response: filterResponse{ + InlineString: "", + }, + }, + }, + expected: "Direct response: -> string: env:POSTGRESS_CONNECTION_STRING", + }, + "Echo": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.echo.v3.Echo", + }, + }, + expected: "Echo: upstream will respond with the data it receives.", + }, + "External Authorization using Envoy gRPC": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz", + GrpcService: filterGrpcService{ + EnvoyGrpc: filterEnvoyGrpc{ + ClusterName: "auth-server", + }, + }, + }, + }, + expected: "External authorization: auth-server", + }, + "External Authorization using Google gRPC": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz", + GrpcService: filterGrpcService{ + GoogleGrpc: filterGoogleGrpc{ + TargetUri: "auth.endpoint", + }, + }, + }, + }, + expected: "External authorization: auth.endpoint", + }, + "External Authorization unset": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.ext_authz.v3.ExtAuthz", + }, + }, + expected: "External authorization: No upstream configured.", + }, + "HTTP Connection Manager": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager", + RouteConfig: filterRouteConfig{ + Name: "public_listener", + VirtualHosts: []filterVirtualHost{ + { + Name: "public_listener", + Domains: []string{"*"}, + Routes: []filterRoute{ + { + Match: filterMatch{ + Prefix: "/", + }, + Route: filterRouteCluster{ + Cluster: "local_app", + }, + }, + }, + }, + }, + }, + }, + }, + expected: "HTTP: * -> local_app/", + }, + "Local Ratelimit": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.local_ratelimit.v3.LocalRateLimit", + TokenBucket: filterTokenBucket{ + MaxTokens: 24, + TokensPerFill: 2, + FillInterval: "20s", + }, + }, + }, + expected: "Local rate limit: tokens: max 24 per-fill 2, interval: 20s", + }, + "Ratelimit with descriptors": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.ratelimit.v3.RateLimit", + Domain: "database-ratelimit", + Descriptors: []filterRateLimitDescriptor{ + { + Entries: []filterRateLimitDescriptorEntry{ + { + Key: "PATH", + Value: "/users", + }, + }, + Limit: filterRateLimitOverride{ + RequestsPerUnit: 42, + Unit: "MINUTE", + }, + }, + }, + }, + }, + expected: "Rate limit: database-ratelimit PATH:/users 42 req per minute", + }, + "Ratelimit with EnvoyGrpc definted limiter allowing failures": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.ratelimit.v3.RateLimit", + Domain: "database-ratelimit", + FailureModeDeny: true, + RateLimitService: filterRateLimitServiceConfig{ + GrpcService: filterGrpcService{ + EnvoyGrpc: filterEnvoyGrpc{ + ClusterName: "ratelimiter.service", + }, + }, + }, + }, + }, + expected: "Rate limit: database-ratelimit using ratelimiter.service will deny if unreachable", + }, + "Ratelimit with GoogleGrpc defined limiter": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.ratelimit.v3.RateLimit", + Domain: "database-ratelimit", + RateLimitService: filterRateLimitServiceConfig{ + GrpcService: filterGrpcService{ + GoogleGrpc: filterGoogleGrpc{ + TargetUri: "ratelimiter.service", + }, + }, + }, + }, + }, + expected: "Rate limit: database-ratelimit using ratelimiter.service", + }, + "RBAC": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.rbac.v3.RBAC", + Rules: filterRules{ + Action: "DENY", + Policies: filterHttpTypedConfigPolicies{ + ConsulIntentions: filterHttpTypedConfigConsulIntentions{ + Principals: []principal{ + { + Authenticated: authenticated{ + PrincipalName: principalName{ + SafeRegex: safeRegex{ + Regex: "^spiffe://[^/]+/ns/default/dc/[^/]+/svc/client$", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + expected: "RBAC: DENY ^spiffe://[^/]+/ns/default/dc/[^/]+/svc/client$", + }, + "SNI Cluster": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.sni_cluster.v3.SniCluster", + }, + }, + expected: "SNI: Upstream cluster name set by SNI field in TLS connection.", + }, + "TCP Proxy with cluster": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + Cluster: "server.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul", + }, + }, + expected: "TCP: -> server", + }, + "TCP Proxy without cluster": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy", + }, + }, + expected: "TCP: No upstream cluster configured.", + }, + "Unknown format": { + filter: filter{ + TypedConfig: filterTypedConfig{ + Type: "type.googleapis.com/envoy.extensions.filters.network.NewFormat", + }, + }, + expected: "Unknown filter: type.googleapis.com/envoy.extensions.filters.network.NewFormat", + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + actual := formatFilters([]filter{tc.filter})[0] + require.Equal(t, tc.expected, actual) + }) + } +} + type mockPortForwarder struct { openBehavior func(context.Context) (string, error) } @@ -117,11 +407,11 @@ var testEnvoyConfig = &EnvoyConfig{ {Address: "127.0.0.1:8080", Cluster: "local_app", Weight: 1, Status: "HEALTHY"}, }, Listeners: []Listener{ - {Name: "public_listener", Address: "192.168.69.179:20000", FilterChain: []FilterChain{{Filters: []string{"* to local_app/"}, FilterChainMatch: "Any"}}, Direction: "INBOUND", LastUpdated: "2022-08-10T12:30:47.142Z"}, + {Name: "public_listener", Address: "192.168.69.179:20000", FilterChain: []FilterChain{{Filters: []string{"HTTP: * -> local_app/"}, FilterChainMatch: "Any"}}, Direction: "INBOUND", LastUpdated: "2022-08-10T12:30:47.142Z"}, {Name: "outbound_listener", Address: "127.0.0.1:15001", FilterChain: []FilterChain{ - {Filters: []string{"to client.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, FilterChainMatch: "10.100.134.173/32, 240.0.0.3/32"}, - {Filters: []string{"to frontend.default.dc1.internal.bc3815c2-1a0f-f3ff-a2e9-20d791f08d00.consul"}, FilterChainMatch: "10.100.31.2/32, 240.0.0.5/32"}, - {Filters: []string{"to original-destination"}, FilterChainMatch: "Any"}, + {Filters: []string{"TCP: -> client"}, FilterChainMatch: "10.100.134.173/32, 240.0.0.3/32"}, + {Filters: []string{"TCP: -> frontend"}, FilterChainMatch: "10.100.31.2/32, 240.0.0.5/32"}, + {Filters: []string{"TCP: -> original-destination"}, FilterChainMatch: "Any"}, }, Direction: "OUTBOUND", LastUpdated: "2022-07-18T15:31:03.246Z"}, }, Routes: []Route{ diff --git a/cli/cmd/proxy/read/envoy_types.go b/cli/cmd/proxy/read/envoy_types.go index 10f76101dd..cc1ffcf7e2 100644 --- a/cli/cmd/proxy/read/envoy_types.go +++ b/cli/cmd/proxy/read/envoy_types.go @@ -106,16 +106,28 @@ type filterChain struct { } type filter struct { - Name string `json:"name"` - TypedConfig typedConfig `json:"typed_config"` -} - -type typedConfig struct { - Type string `json:"@type"` - Cluster string `json:"cluster"` - RouteConfig filterRouteConfig `json:"route_config"` - HttpFilters []httpFilter `json:"http_filters"` - Rules rules `json:"rules"` + Name string `json:"name"` + TypedConfig filterTypedConfig `json:"typed_config"` +} + +// Not all filters have all of these values. This is extensive to cover the +// numerous configuration types for filters. +type filterTypedConfig struct { + Type string `json:"@type"` + Cluster string `json:"cluster"` + RouteConfig filterRouteConfig `json:"route_config"` + HttpFilters []httpFilter `json:"http_filters"` + Rules filterRules `json:"rules"` + StatPrefix string `json:"stat_prefix"` + MaxConnections int64 `json:"max_connections"` + Delay string `json:"delay"` + Response filterResponse `json:"reponse"` + GrpcService filterGrpcService `json:"grpc_service"` + TokenBucket filterTokenBucket `json:"token_bucket"` + Domain string `json:"domain"` + Descriptors []filterRateLimitDescriptor `json:"descriptors"` + FailureModeDeny bool `json:"failure_mode_deny"` + RateLimitService filterRateLimitServiceConfig `json:"rate_limit_service"` } type filterRouteConfig struct { @@ -156,19 +168,19 @@ type httpFilter struct { } type httpTypedConfig struct { - Rules rules `json:"rules"` + Rules filterRules `json:"rules"` } -type rules struct { - Action string `json:"action"` - Policies httpTypedConfigPolicies `json:"policies"` +type filterRules struct { + Action string `json:"action"` + Policies filterHttpTypedConfigPolicies `json:"policies"` } -type httpTypedConfigPolicies struct { - ConsulIntentions httpTypedConfigConsulIntentions `json:"consul-intentions-layer4"` +type filterHttpTypedConfigPolicies struct { + ConsulIntentions filterHttpTypedConfigConsulIntentions `json:"consul-intentions-layer4"` } -type httpTypedConfigConsulIntentions struct { +type filterHttpTypedConfigConsulIntentions struct { Principals []principal `json:"principals"` } @@ -220,6 +232,51 @@ type routeRoute struct { Cluster string `json:"cluster"` } +type filterResponse struct { + Filename string `json:"filename"` + InlineBytes []byte `json:"inline_bytes"` + InlineString string `json:"inline_string"` + EnvironmentVariable string `json:"environment_variable"` +} + +type filterGrpcService struct { + EnvoyGrpc filterEnvoyGrpc `json:"envoy_grpc"` + GoogleGrpc filterGoogleGrpc `json:"google_grpc"` +} + +type filterEnvoyGrpc struct { + ClusterName string `json:"cluster_name"` +} + +type filterGoogleGrpc struct { + TargetUri string `json:"target_uri"` +} + +type filterTokenBucket struct { + MaxTokens int `json:"max_tokens"` + TokensPerFill int `json:"tokens_per_fill"` + FillInterval string `json:"fill_interval"` +} + +type filterRateLimitDescriptor struct { + Entries []filterRateLimitDescriptorEntry `json:"entries"` + Limit filterRateLimitOverride `json:"limit"` +} + +type filterRateLimitDescriptorEntry struct { + Key string `json:"key"` + Value string `json:"value"` +} + +type filterRateLimitOverride struct { + RequestsPerUnit int `json:"requests_per_unit"` + Unit string `json:"unit"` +} + +type filterRateLimitServiceConfig struct { + GrpcService filterGrpcService `json:"grpc_service"` +} + type secretsConfigDump struct { ConfigType string `json:"@type"` StaticSecrets []secretConfigMap `json:"static_secrets"` diff --git a/cli/common/portforward.go b/cli/common/portforward.go index a2acd02d27..4cca979ac6 100644 --- a/cli/common/portforward.go +++ b/cli/common/portforward.go @@ -103,7 +103,7 @@ func (pf *PortForward) Open(ctx context.Context) (string, error) { case <-ctx.Done(): pf.Close() return "", fmt.Errorf("port forward cancelled") - case <-time.After(time.Second * 5): + case <-time.After(time.Second * 10): pf.Close() return "", fmt.Errorf("port forward timed out") } From 37ac3e5290226cfcd00bbd54dbfaea1df06e8164 Mon Sep 17 00:00:00 2001 From: David Yu Date: Wed, 31 Aug 2022 08:30:01 -0700 Subject: [PATCH 110/235] CHANGELOG: formatting and missing links (#1467) --- CHANGELOG.md | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1689aa193..5e9af5f69f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,45 +6,46 @@ FEATURES: * Consul CNI Plugin * CNI Plugin for Consul-k8s [[GH-1465](https://github.com/hashicorp/consul-k8s/pull/1456)] * Kubernetes 1.24 Support - * Add support for Kubernetes 1.24 where ServiceAccounts no longer have long term JWT tokens. [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] + * Add support for Kubernetes 1.24 where ServiceAccounts no longer have long-term JWT tokens. [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] * Upgrade kubeVersion in helm chart to support Kubernetes 1.21+. BREAKING CHANGES: * Kubernetes 1.24 Support - * Users deploying multiple services to the same Pod (multiport) on Kubernetes 1.24+ must also deploy a Kube Secret for each ServiceAccount associated with the Consul service. The name of the Secret must match the ServiceAccount name and be of type 'kubernetes.io/service-account-token' + * Users deploying multiple services to the same Pod (multiport) on Kubernetes 1.24+ must also deploy a Kubernetes Secret for each ServiceAccount associated with the Consul service. The name of the Secret must match the ServiceAccount name and be of type `kubernetes.io/service-account-token` [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] -Example: -```yaml -apiVersion: v1 -kind: Secret -metadata: - name: svc1 - annotations: - kubernetes.io/service-account.name: svc1 -type: kubernetes.io/service-account-token ---- -apiVersion: v1 -kind: Secret -metadata: - name: svc2 - annotations: - kubernetes.io/service-account.name: svc2 -type: kubernetes.io/service-account-token -``` + Example: + + ```yaml + apiVersion: v1 + kind: Secret + metadata: + name: svc1 + annotations: + kubernetes.io/service-account.name: svc1 + type: kubernetes.io/service-account-token + --- + apiVersion: v1 + kind: Secret + metadata: + name: svc2 + annotations: + kubernetes.io/service-account.name: svc2 + type: kubernetes.io/service-account-token + ``` IMPROVEMENTS: * CLI: * Display clusters by their short names rather than FQDNs for the `proxy read` command. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a message when `proxy list` returns no results. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] - * Extend the timeout for `consul-k8s proxy read` to establish a connection from 5s to 10s. - * Expand the set of Envoy Listener Filters that may be parsed and output to the Listeners table. + * Extend the timeout for `consul-k8s proxy read` to establish a connection from 5s to 10s. [[GH-1442](https://github.com/hashicorp/consul-k8s/pull/1442)] + * Expand the set of Envoy Listener Filters that may be parsed and output to the Listeners table. [[GH-1442](https://github.com/hashicorp/consul-k8s/pull/1442)] BUG FIXES: * Helm * API Gateway: Configure ACL auth for controller correctly when deployed in secondary datacenter with federation enabled [[GH-1462](https://github.com/hashicorp/consul-k8s/pull/1462)] * CLI - * Fix issue where SNI filters for Terminating Gateways showed up as blank lines. + * Fix issue where SNI filters for Terminating Gateways showed up as blank lines. [[GH-1442](https://github.com/hashicorp/consul-k8s/pull/1442)] ## 0.47.1 (August 12, 2022) From b8af65262de8c44b6a2370bdd2912b43832cfc24 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Wed, 31 Aug 2022 13:48:02 -0400 Subject: [PATCH 111/235] Omit non-IP defined endpoints from clusters (#1452) * Omit non-IP defined endpoints from clusters * Improve perf with regex * Use ParseIP instead of RegEx * Add test for parseClusters --- cli/cmd/proxy/read/config.go | 7 ++- cli/cmd/proxy/read/config_test.go | 74 +++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) diff --git a/cli/cmd/proxy/read/config.go b/cli/cmd/proxy/read/config.go index 3c1a105c0e..e7e6bcad34 100644 --- a/cli/cmd/proxy/read/config.go +++ b/cli/cmd/proxy/read/config.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "net" "net/http" "strings" @@ -198,8 +199,10 @@ func parseClusters(rawCfg map[string]interface{}, clusterMapping map[string][]st endpoints := make([]string, 0) for _, endpoint := range cluster.Cluster.LoadAssignment.Endpoints { for _, lbEndpoint := range endpoint.LBEndpoints { - endpoints = append(endpoints, fmt.Sprintf("%s:%d", lbEndpoint.Endpoint.Address.SocketAddress.Address, - int(lbEndpoint.Endpoint.Address.SocketAddress.PortValue))) + // Only add endpoints defined by IP addresses. + if addr := lbEndpoint.Endpoint.Address.SocketAddress.Address; net.ParseIP(addr) != nil { + endpoints = append(endpoints, fmt.Sprintf("%s:%d", addr, int(lbEndpoint.Endpoint.Address.SocketAddress.PortValue))) + } } } diff --git a/cli/cmd/proxy/read/config_test.go b/cli/cmd/proxy/read/config_test.go index 243523698f..6b0e425794 100644 --- a/cli/cmd/proxy/read/config_test.go +++ b/cli/cmd/proxy/read/config_test.go @@ -372,6 +372,80 @@ func TestFormatFilters(t *testing.T) { } } +// TestClusterParsingEndpoints checks that the parseClusters function correctly +// maps endpoints from the config dump and cluster mapping into a config object. +// This includes omitting endpoints that are defined by domain names as seen in +// Logical DNS clusters. +func TestClusterParsingEndpoints(t *testing.T) { + expected := []Cluster{ + { + Name: "logical_dns_cluster", + FullyQualifiedDomainName: "logical_dns_cluster.service.host", + Endpoints: []string{"192.168.18.110:20000", "192.168.52.101:20000", "192.168.65.131:20000"}, + Type: "LOGICAL_DNS", + LastUpdated: "2022-08-30T12:31:03.354Z", + }, + } + + rawCfg := map[string]interface{}{ + "dynamic_active_clusters": []map[string]interface{}{ + { + "cluster": map[string]interface{}{ + "name": "logical_dns_cluster.service.host", + "type": "LOGICAL_DNS", + "load_assignment": map[string]interface{}{ + "endpoints": []map[string]interface{}{ + { + "lb_endpoints": []map[string]interface{}{ + { + "endpoint": map[string]interface{}{ + "address": map[string]interface{}{ + "socket_address": map[string]interface{}{ + "address": "192.168.18.110", + "port_value": 20000, + }, + }, + }, + }, + { + "endpoints": map[string]interface{}{ + "address": map[string]interface{}{ + "socket_address": map[string]interface{}{ + "address": "192.168.52.101", + "port_value": 20000, + }, + }, + }, + }, + { + "endpoints": map[string]interface{}{ + "address": map[string]interface{}{ + "socket_address": map[string]interface{}{ + "address": "domain-name", + "port_value": 20000, + }, + }, + }, + }, + }, + }, + }, + }, + }, + "last_updated": "2022-08-30T12:31:03.354Z", + }, + }, + } + clusterMapping := map[string][]string{ + "logical_dns_cluster.service.host": {"192.168.52.101:20000", "192.168.65.131:20000"}, + } + + actual, err := parseClusters(rawCfg, clusterMapping) + require.NoError(t, err) + + require.Equal(t, expected, actual) +} + type mockPortForwarder struct { openBehavior func(context.Context) (string, error) } From 9e6b1f71f338bb90b8a83bf244951d0194c84466 Mon Sep 17 00:00:00 2001 From: John Murret Date: Thu, 1 Sep 2022 10:54:52 -0600 Subject: [PATCH 112/235] Update the reference to cni package to the current on main. (#1472) --- control-plane/go.mod | 3 ++- control-plane/go.sum | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/control-plane/go.mod b/control-plane/go.mod index 1be842ad95..50b1c65a2e 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -8,7 +8,6 @@ require ( github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f @@ -52,6 +51,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/containernetworking/plugins v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 // indirect github.com/digitalocean/godo v1.10.0 // indirect @@ -69,6 +69,7 @@ require ( github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/googleapis/gnostic v0.5.5 // indirect github.com/gophercloud/gophercloud v0.1.0 // indirect + github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.0 // indirect diff --git a/control-plane/go.sum b/control-plane/go.sum index b42a9dca6b..3d48c2626a 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -138,6 +138,8 @@ github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoC github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/containernetworking/cni v1.1.1 h1:ky20T7c0MvKvbMOwS/FrlbNwjEoqJEUUYfsL4b0mc4k= github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= +github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNGz0C1d3wVYlHE= +github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -335,6 +337,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a h1:cBwGTYV84M0W8PwHX6+PywY8NiP3dzA7JaZzs9+LdiA= github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a/go.mod h1:aw35GB76URgbtxaSSMxbOetbG7YEHHPkIX3/SkTBaWc= +github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 h1:TQY0oKtLV15UNYWeSkTxi4McBIyLecsEtbc/VfxvbYA= +github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8/go.mod h1:aw35GB76URgbtxaSSMxbOetbG7YEHHPkIX3/SkTBaWc= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 h1:csNww5qBHaFqsX1eMEKVvmJ4dhqcXWj0sCkbccsSsHc= github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= From 1ffa44ab2b89d63440f9cd70f98233259fa831c7 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 1 Sep 2022 14:02:34 -0500 Subject: [PATCH 113/235] update Kubernetes versions throughout CI (#1460) * update Kube versions throughout CI so nightlies run against supported versions of Kubernetes. --- .circleci/config.yml | 112 ++++------------------- charts/consul/test/terraform/eks/main.tf | 2 +- charts/consul/test/terraform/gke/main.tf | 2 +- 3 files changed, 20 insertions(+), 96 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 7743a5d811..f321206381 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -538,7 +538,7 @@ jobs: - checkout - install-prereqs - create-kind-clusters: - version: "v1.22.4" + version: "v1.24.0" - restore_cache: keys: - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} @@ -570,7 +570,7 @@ jobs: - checkout - install-prereqs - create-kind-clusters: - version: "v1.22.4" + version: "v1.24.0" - restore_cache: keys: - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} @@ -653,8 +653,8 @@ jobs: ######################## # ACCEPTANCE TESTS ######################## - acceptance-gke-1-20: - parallelism: 6 + acceptance-gke-1-23: + parallelism: 2 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -721,8 +721,8 @@ jobs: fail_only: true failure_message: "GKE acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-gke-cni-1-20: - parallelism: 3 + acceptance-gke-cni-1-23: + parallelism: 2 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -789,8 +789,8 @@ jobs: fail_only: true failure_message: "GKE CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-aks-1-21: - parallelism: 6 + acceptance-aks-1-22: + parallelism: 3 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -846,7 +846,7 @@ jobs: fail_only: true failure_message: "AKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-aks-cni-1-21: + acceptance-aks-cni-1-22: parallelism: 3 environment: - TEST_RESULTS: /tmp/test-results @@ -902,8 +902,8 @@ jobs: fail_only: true failure_message: "AKS CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-eks-1-19: - parallelism: 6 + acceptance-eks-1-21: + parallelism: 3 environment: - TEST_RESULTS: /tmp/test-results docker: @@ -965,7 +965,7 @@ jobs: fail_only: true failure_message: "EKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-eks-cni-1-19: + acceptance-eks-cni-1-21: parallelism: 3 environment: - TEST_RESULTS: /tmp/test-results @@ -1082,76 +1082,6 @@ jobs: fail_only: true failure_message: "OpenShift acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-kind-1-23: - parallelism: 6 - environment: - - TEST_RESULTS: /tmp/test-results - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.23.0" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "Acceptance tests against Kind with Kubernetes v1.23 failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-kind-cni-1-23: - parallelism: 3 - environment: - - TEST_RESULTS: /tmp/test-results - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - steps: - - checkout - - install-prereqs - - create-kind-cni-clusters: - version: "v1.23.0" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -enable-cni - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "Acceptance tests for CNI against Kind with Kubernetes v1.23 failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-kind-1-23-consul-nightly-1-11: environment: - TEST_RESULTS: /tmp/test-results @@ -1318,36 +1248,30 @@ workflows: # - acceptance-openshift: # requires: # - cleanup-azure-resources - - acceptance-gke-1-20: + - acceptance-gke-1-23: requires: - cleanup-gcp-resources - dev-upload-docker - - acceptance-gke-cni-1-20: + - acceptance-gke-cni-1-23: requires: - cleanup-gcp-resources - dev-upload-docker - - acceptance-eks-1-19: + - acceptance-eks-1-21: requires: - cleanup-eks-resources - dev-upload-docker - - acceptance-eks-cni-1-19: + - acceptance-eks-cni-1-21: requires: - cleanup-eks-resources - dev-upload-docker - - acceptance-aks-1-21: + - acceptance-aks-1-22: requires: - cleanup-azure-resources - dev-upload-docker - - acceptance-aks-cni-1-21: + - acceptance-aks-cni-1-22: requires: - cleanup-azure-resources - dev-upload-docker - - acceptance-kind-1-23: - requires: - - dev-upload-docker - - acceptance-kind-cni-1-23: - requires: - - dev-upload-docker nightly-acceptance-tests-consul: triggers: diff --git a/charts/consul/test/terraform/eks/main.tf b/charts/consul/test/terraform/eks/main.tf index ad9538ac51..19b8cb1229 100644 --- a/charts/consul/test/terraform/eks/main.tf +++ b/charts/consul/test/terraform/eks/main.tf @@ -57,7 +57,7 @@ module "eks" { version = "17.20.0" cluster_name = "consul-k8s-${random_id.suffix[count.index].dec}" - cluster_version = "1.20" + cluster_version = "1.21" subnets = module.vpc[count.index].private_subnets vpc_id = module.vpc[count.index].vpc_id diff --git a/charts/consul/test/terraform/gke/main.tf b/charts/consul/test/terraform/gke/main.tf index 4004b3e73d..1574df36b3 100644 --- a/charts/consul/test/terraform/gke/main.tf +++ b/charts/consul/test/terraform/gke/main.tf @@ -10,7 +10,7 @@ resource "random_id" "suffix" { data "google_container_engine_versions" "main" { location = var.zone - version_prefix = "1.21." + version_prefix = "1.23." } resource "google_container_cluster" "cluster" { From db0dce0aa2d21548b1a662165a0302847c810ebc Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Thu, 1 Sep 2022 15:19:18 -0500 Subject: [PATCH 114/235] release 0.48.0 (#1473) * release 0.48.0 * update envoy version to 1.23.1 --- CHANGELOG.md | 11 +++++++++-- charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 4 ++-- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 5 files changed, 18 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e9af5f69f..43464dcfc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.48.0 (September 01, 2022) FEATURES: * MaxInboundConnections in service-defaults CRD @@ -11,7 +11,8 @@ FEATURES: BREAKING CHANGES: * Kubernetes 1.24 Support - * Users deploying multiple services to the same Pod (multiport) on Kubernetes 1.24+ must also deploy a Kubernetes Secret for each ServiceAccount associated with the Consul service. The name of the Secret must match the ServiceAccount name and be of type `kubernetes.io/service-account-token` [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] + * Users deploying multiple services to the same Pod (multiport) on Kubernetes 1.24 must also deploy a Kubernetes Secret for each ServiceAccount associated with the Consul service. The name of the Secret must match the ServiceAccount name and be of type `kubernetes.io/service-account-token` [[GH-1431](https://github.com/hashicorp/consul-k8s/pull/1431)] + * Kubernetes 1.19 and 1.20 are no longer supported. Example: @@ -33,6 +34,9 @@ BREAKING CHANGES: type: kubernetes.io/service-account-token ``` +* Control Plane + * Rename flag `server-address` to `token-server-address` in the `inject-connect` subcommand to avoid overloading the context of the `server-address` flag. [[GH-1426](https://github.com/hashicorp/consul-k8s/pull/1426)] + IMPROVEMENTS: * CLI: * Display clusters by their short names rather than FQDNs for the `proxy read` command. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] @@ -40,12 +44,15 @@ IMPROVEMENTS: * Display a warning when a user passes a field and table filter combination to `proxy read` where the given field is not present in any of the output tables. [[GH-1412](https://github.com/hashicorp/consul-k8s/pull/1412)] * Extend the timeout for `consul-k8s proxy read` to establish a connection from 5s to 10s. [[GH-1442](https://github.com/hashicorp/consul-k8s/pull/1442)] * Expand the set of Envoy Listener Filters that may be parsed and output to the Listeners table. [[GH-1442](https://github.com/hashicorp/consul-k8s/pull/1442)] +* Helm: + * The default Envoy proxy image is now `envoyproxy/envoy:v1.23.1`. [[GH-1473](https://github.com/hashicorp/consul-k8s/pull/1473)] BUG FIXES: * Helm * API Gateway: Configure ACL auth for controller correctly when deployed in secondary datacenter with federation enabled [[GH-1462](https://github.com/hashicorp/consul-k8s/pull/1462)] * CLI * Fix issue where SNI filters for Terminating Gateways showed up as blank lines. [[GH-1442](https://github.com/hashicorp/consul-k8s/pull/1442)] + * Fix issue where Logical DNS endpoints were being displayed alongside cluster names. [[GH-1452](https://github.com/hashicorp/consul-k8s/pull/1452)] ## 0.47.1 (August 12, 2022) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 223400f17a..a2209ac9b6 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.47.1 +version: 0.48.0 appVersion: 1.13.1 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -15,9 +15,9 @@ annotations: - name: consul image: hashicorp/consul:1.13.1 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.47.1 + image: hashicorp/consul-k8s-control-plane:0.48.0 - name: envoy - image: envoyproxy/envoy:v1.22.4 + image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 artifacthub.io/links: | - name: Documentation diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 7f00ef6ef2..f94135e5e1 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.47.1 + imageK8S: hashicorp/consul-k8s-control-plane:0.48.0 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running @@ -629,7 +629,7 @@ global: # connect-injected sidecar proxies and mesh, terminating, and ingress gateways. # See https://www.consul.io/docs/connect/proxies/envoy for full compatibility matrix between Consul and Envoy. # @default: envoyproxy/envoy-alpine: - imageEnvoy: "envoyproxy/envoy:v1.22.4" + imageEnvoy: "envoyproxy/envoy:v1.23.1" # Configuration for running this Helm chart on the Red Hat OpenShift platform. # This Helm chart currently supports OpenShift v4.x+. diff --git a/cli/version/version.go b/cli/version/version.go index 9106f59bc7..44adbf8746 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.47.1" + Version = "0.48.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 9106f59bc7..44adbf8746 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.47.1" + Version = "0.48.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 06923dec57e53cdc025731c2c7a9a508eb114e27 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Fri, 2 Sep 2022 13:33:21 -0500 Subject: [PATCH 115/235] put main back into dev (#1476) --- CHANGELOG.md | 2 ++ cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43464dcfc6..0090c797bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.48.0 (September 01, 2022) FEATURES: diff --git a/cli/version/version.go b/cli/version/version.go index 44adbf8746..b74b5fa468 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 44adbf8746..b74b5fa468 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 7ea278f3dde6bc3387404348429652d0de6d4d9d Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Fri, 2 Sep 2022 16:39:15 -0500 Subject: [PATCH 116/235] update acceptance tests to use latest consul-k8s release (#1477) --- .circleci/config.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f321206381..908169daf8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1087,8 +1087,8 @@ jobs: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.11-dev" - ENVOY_IMAGE: "envoyproxy/envoy:v1.20.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.47.1" - - HELM_CHART_VERSION: "0.47.1" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.48.0" + - HELM_CHART_VERSION: "0.48.0" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -1125,8 +1125,8 @@ jobs: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.12-dev" - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" - - HELM_CHART_VERSION: "0.47.1" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.47.1" + - HELM_CHART_VERSION: "0.48.0" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.48.0" machine: image: ubuntu-2004:202010-01 resource_class: xlarge @@ -1162,9 +1162,9 @@ jobs: environment: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev" - - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.47.1" - - HELM_CHART_VERSION: "0.47.1" + - ENVOY_IMAGE: "envoyproxy/envoy:v1.23.1" + - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.48.0" + - HELM_CHART_VERSION: "0.48.0" machine: image: ubuntu-2004:202010-01 resource_class: xlarge From beff736456c330801882f5c0b80e766005b4e267 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Sep 2022 10:40:18 -0500 Subject: [PATCH 117/235] Bump helm.sh/helm/v3 from 3.6.1 to 3.9.4 in /cli (#1465) Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.6.1 to 3.9.4. - [Release notes](https://github.com/helm/helm/releases) - [Commits](https://github.com/helm/helm/compare/v3.6.1...v3.9.4) --- updated-dependencies: - dependency-name: helm.sh/helm/v3 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- cli/go.mod | 165 +++++---- cli/go.sum | 1028 +++++++++++++++++++++++++++------------------------- 2 files changed, 619 insertions(+), 574 deletions(-) diff --git a/cli/go.mod b/cli/go.mod index 00c718a139..f130971e0a 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -5,158 +5,155 @@ go 1.18 require ( github.com/bgentry/speakeasy v0.1.0 github.com/cenkalti/backoff v2.2.1+incompatible - github.com/fatih/color v1.9.0 - github.com/google/go-cmp v0.5.5 + github.com/fatih/color v1.13.0 + github.com/google/go-cmp v0.5.6 github.com/hashicorp/consul-k8s/charts v0.0.0-00010101000000-000000000000 github.com/hashicorp/go-hclog v0.16.2 github.com/kr/text v0.2.0 - github.com/mattn/go-isatty v0.0.12 + github.com/mattn/go-isatty v0.0.14 github.com/mitchellh/cli v1.1.2 - github.com/olekukonko/tablewriter v0.0.4 + github.com/olekukonko/tablewriter v0.0.5 github.com/posener/complete v1.1.1 - github.com/stretchr/testify v1.7.0 - helm.sh/helm/v3 v3.6.1 - k8s.io/api v0.22.2 - k8s.io/apimachinery v0.22.2 - k8s.io/cli-runtime v0.21.0 - k8s.io/client-go v0.22.2 - k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a - sigs.k8s.io/yaml v1.2.0 + github.com/stretchr/testify v1.7.2 + helm.sh/helm/v3 v3.9.4 + k8s.io/api v0.24.2 + k8s.io/apimachinery v0.24.2 + k8s.io/cli-runtime v0.24.2 + k8s.io/client-go v0.24.2 + k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 + sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go v0.54.0 // indirect + cloud.google.com/go v0.99.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.18 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect + github.com/Azure/go-autorest/autorest v0.11.24 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/BurntSushi/toml v0.3.1 // indirect + github.com/BurntSushi/toml v1.0.0 // indirect github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/Masterminds/squirrel v1.5.0 // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/Microsoft/hcsshim v0.8.14 // indirect + github.com/Masterminds/squirrel v1.5.3 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 // indirect - github.com/containerd/containerd v1.4.4 // indirect - github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 // indirect - github.com/cyphar/filepath-securejoin v0.2.2 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect + github.com/containerd/containerd v1.6.6 // indirect + github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deislabs/oras v0.11.1 // indirect - github.com/docker/cli v20.10.5+incompatible // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect - github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.3 // indirect + github.com/docker/cli v20.10.17+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/docker v20.10.17+incompatible // indirect + github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect + github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/evanphx/json-patch v4.11.0+incompatible // indirect + github.com/emicklei/go-restful/v3 v3.8.0 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect - github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect github.com/go-errors/errors v1.0.1 // indirect - github.com/go-logr/logr v0.4.0 // indirect - github.com/go-openapi/jsonpointer v0.19.3 // indirect - github.com/go-openapi/jsonreference v0.19.3 // indirect - github.com/go-openapi/spec v0.19.5 // indirect + github.com/go-gorp/gorp/v3 v3.0.2 // indirect + github.com/go-logr/logr v1.2.2 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/googleapis/gnostic v0.5.5 // indirect - github.com/gorilla/mux v1.7.3 // indirect + github.com/google/uuid v1.2.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.11 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jmoiron/sqlx v1.3.1 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.11 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.13.6 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/lib/pq v1.10.0 // indirect + github.com/lib/pq v1.10.6 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mattn/go-runewidth v0.0.7 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/mitchellh/copystructure v1.1.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mitchellh/reflectwalk v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect - github.com/opencontainers/runc v0.1.1 // indirect + github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/rubenv/sql-migrate v1.1.1 // indirect github.com/russross/blackfriday v1.5.2 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/cobra v1.1.3 // indirect + github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/cobra v1.4.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect - go.opencensus.io v0.22.3 // indirect go.starlark.net v0.0.0-20200707032745-474f21a9602d // indirect - golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect + golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect - google.golang.org/appengine v1.6.5 // indirect - google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect - google.golang.org/grpc v1.36.0 // indirect + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect + google.golang.org/grpc v1.43.0 // indirect google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/gorp.v1 v1.7.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/apiextensions-apiserver v0.21.0 // indirect - k8s.io/apiserver v0.21.0 // indirect - k8s.io/component-base v0.21.0 // indirect - k8s.io/klog/v2 v2.9.0 // indirect - k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect - k8s.io/kubectl v0.21.0 // indirect - rsc.io/letsencrypt v0.0.3 // indirect - sigs.k8s.io/kustomize/api v0.8.5 // indirect - sigs.k8s.io/kustomize/kyaml v0.10.15 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.24.2 // indirect + k8s.io/apiserver v0.24.2 // indirect + k8s.io/component-base v0.24.2 // indirect + k8s.io/klog/v2 v2.60.1 // indirect + k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 // indirect + k8s.io/kubectl v0.24.2 // indirect + oras.land/oras-go v1.2.0 // indirect + sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect + sigs.k8s.io/kustomize/api v0.11.4 // indirect + sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect ) // This replace directive is to avoid having to manually bump the version of the charts module upon changes to the Helm diff --git a/cli/go.sum b/cli/go.sum index d65d9b4ff1..13d8d9c526 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -9,50 +8,67 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= +github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= +github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -66,284 +82,208 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/Y8cY8= -github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= -github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= +github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= +github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= +github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= +github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0= +github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/deislabs/oras v0.11.1 h1:oo2J/3vXdcti8cjFi8ghMOkx0OacONxHC8dhJ17NdJ0= -github.com/deislabs/oras v0.11.1/go.mod h1:39lCtf8Q6WDC7ul9cnyWXONNzKvabEKk+AX+L0ImnQk= -github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE= -github.com/docker/cli v20.10.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8= -github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269 h1:hbCT8ZPPMqefiAWD2ZKjn7ypokIGViTvBBg/ExLSdCk= +github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= +github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-gorp/gorp/v3 v3.0.2 h1:ULqJXIekoqMx29FI5ekXXFoH1dT2Vc8UhnRzBg+Emz4= +github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= -github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= -github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw= -github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= -github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= -github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= -github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= -github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= -github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg= -github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= -github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= -github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= -github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o= -github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= +github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= +github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= +github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= +github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= +github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= +github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= -github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -355,11 +295,16 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -369,85 +314,99 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= +github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -460,48 +419,50 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE= -github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= +github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -510,43 +471,41 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtB github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= +github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= +github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= +github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= +github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= +github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -557,8 +516,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4= -github.com/mitchellh/copystructure v1.1.1/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -569,202 +528,153 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= -github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= -github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= 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= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1 h1:oL4IBbcqwhhNWh31bjOX8C/OCy0zs9906d/VUru+bqg= +github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.4.0 h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY= -github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 h1:HXr/qUllAWv9riaI4zh2eXWKmCSDqVS/XH1MRHLKRwk= -github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY= +github.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -774,18 +684,12 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= @@ -795,64 +699,78 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= +go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= +go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= +go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= +go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= +go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.starlark.net v0.0.0-20200707032745-474f21a9602d h1:uFqwFYlX7d5ZSp+IqhXxct0SybXrTzEBDvb2CkEhPBs= go.starlark.net v0.0.0-20200707032745-474f21a9602d/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -875,6 +793,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -883,32 +803,29 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -916,29 +833,63 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -946,86 +897,102 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1035,17 +1002,13 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1054,7 +1017,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1062,18 +1024,38 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1083,21 +1065,41 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1110,27 +1112,80 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM= +google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1147,106 +1202,99 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= -gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -helm.sh/helm/v3 v3.6.1 h1:TQ6q4pAatXr7qh2fbLcb0oNd0I3J7kv26oo5cExKTtc= -helm.sh/helm/v3 v3.6.1/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +helm.sh/helm/v3 v3.9.4 h1:TCI1QhJUeLVOdccfdw+vnSEO3Td6gNqibptB04QtExY= +helm.sh/helm/v3 v3.9.4/go.mod h1:3eaWAIqzvlRSD06gR9MMwmp2KBKwlu9av1/1BZpjeWY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= -k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= -k8s.io/apiextensions-apiserver v0.21.0 h1:Nd4uBuweg6ImzbxkC1W7xUNZcCV/8Vt10iTdTIVF3hw= -k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc= -k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= -k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apiserver v0.21.0 h1:1hWMfsz+cXxB77k6/y0XxWxwl6l9OF26PC9QneUVn1Q= -k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= -k8s.io/cli-runtime v0.21.0 h1:/V2Kkxtf6x5NI2z+Sd/mIrq4FQyQ8jzZAUD6N5RnN7Y= -k8s.io/cli-runtime v0.21.0/go.mod h1:XoaHP93mGPF37MkLbjGVYqg3S1MnsFdKtiA/RZzzxOo= -k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= -k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= -k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= -k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= -k8s.io/component-base v0.21.0 h1:tLLGp4BBjQaCpS/KiuWh7m2xqvAdsxLm4ATxHSe5Zpg= -k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw= -k8s.io/component-helpers v0.21.0/go.mod h1:tezqefP7lxfvJyR+0a+6QtVrkZ/wIkyMLK4WcQ3Cj8U= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI= +k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= +k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k= +k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ= +k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM= +k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apiserver v0.24.2 h1:orxipm5elPJSkkFNlwH9ClqaKEDJJA3yR2cAAlCnyj4= +k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI= +k8s.io/cli-runtime v0.24.2 h1:KxY6tSgPGsahA6c1/dmR3uF5jOxXPx2QQY6C5ZrLmtE= +k8s.io/cli-runtime v0.24.2/go.mod h1:1LIhKL2RblkhfG4v5lZEt7FtgFG5mVb8wqv5lE9m5qY= +k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA= +k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= +k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= +k8s.io/component-base v0.24.2 h1:kwpQdoSfbcH+8MPN4tALtajLDfSfYxBDYlXobNWI6OU= +k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM= +k8s.io/component-helpers v0.24.2/go.mod h1:TRQPBQKfmqkmV6c0HAmUs8cXVNYYYLsXy4zu8eODi9g= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= +k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= +k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kubectl v0.21.0 h1:WZXlnG/yjcE4LWO2g6ULjFxtzK6H1TKzsfaBFuVIhNg= -k8s.io/kubectl v0.21.0/go.mod h1:EU37NukZRXn1TpAkMUoy8Z/B2u6wjHDS4aInsDzVvks= -k8s.io/metrics v0.21.0/go.mod h1:L3Ji9EGPP1YBbfm9sPfEXSpnj8i24bfQbAFAsW0NueQ= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= +k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 h1:yEQKdMCjzAOvGeiTwG4hO/hNVNtDOuUFvMUZ0OlaIzs= +k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8/go.mod h1:mbJ+NSUoAhuR14N0S63bPkh8MGVSo3VYSGZtH/mfMe0= +k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= +k8s.io/kubectl v0.24.2/go.mod h1:+HIFJc0bA6Tzu5O/YcuUt45APAxnNL8LeMuXwoiGsPg= +k8s.io/metrics v0.24.2/go.mod h1:5NWURxZ6Lz5gj8TFU83+vdWIVASx7W8lwPpHYCqopMo= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +oras.land/oras-go v1.2.0 h1:yoKosVIbsPoFMqAIFHTnrmOuafHal+J/r+I5bdbVWu4= +oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= -rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/kustomize/api v0.8.5 h1:bfCXGXDAbFbb/Jv5AhMj2BB8a5VAJuuQ5/KU69WtDjQ= -sigs.k8s.io/kustomize/api v0.8.5/go.mod h1:M377apnKT5ZHJS++6H4rQoCHmWtt6qTpp3mbe7p6OLY= -sigs.k8s.io/kustomize/cmd/config v0.9.7/go.mod h1:MvXCpHs77cfyxRmCNUQjIqCmZyYsbn5PyQpWiq44nW0= -sigs.k8s.io/kustomize/kustomize/v4 v4.0.5/go.mod h1:C7rYla7sI8EnxHE/xEhRBSHMNfcL91fx0uKmUlUhrBk= -sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI= -sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= +sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= +sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= +sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= +sigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs= +sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= From 03f3072e4bca5ebc3872bb7db842bf8407f4e157 Mon Sep 17 00:00:00 2001 From: Tu Nguyen Date: Mon, 12 Sep 2022 11:51:09 -0700 Subject: [PATCH 118/235] Update docs storageclass (#1493) * Update storageclass docs - link to ref arch --- charts/consul/values.yaml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index f94135e5e1..70ed773cf2 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -741,13 +741,18 @@ server: # The StorageClass to use for the servers' StatefulSet storage. It must be # able to be dynamically provisioned if you want the storage - # to be automatically created. For example, to use local - # (https://kubernetes.io/docs/concepts/storage/storage-classes/#local) + # to be automatically created. For example, to use + # local(https://kubernetes.io/docs/concepts/storage/storage-classes/#local) # storage classes, the PersistentVolumeClaims would need to be manually created. # A `null` value will use the Kubernetes cluster's default StorageClass. If a default # StorageClass does not exist, you will need to create one. - # See https://www.consul.io/docs/install/performance#read-write-tuning for considerations around choosing a - # performant storage class. + # Refer to the [Read/Write Tuning](https://www.consul.io/docs/install/performance#read-write-tuning) + # section of the Server Performance Requirements documentation for considerations + # around choosing a performant storage class. + # + # ~> **Note:** The [Reference Architecture](https://learn.hashicorp.com/tutorials/consul/reference-architecture#hardware-sizing-for-consul-servers) + # contains best practices and recommendations for selecting suitable + # hardware sizes for your Consul servers. # @type: string storageClass: null From a3b31a9f5453824de58cbe02b4d2ad898c756a16 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 12 Sep 2022 15:11:50 -0400 Subject: [PATCH 119/235] Notify #feed-consul-k8s-ci (#1494) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 908169daf8..f09a2f1877 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -10,7 +10,7 @@ executors: environment: TEST_RESULTS: /tmp/test-results # path to where test results are saved -slack-channel: &slack-channel CBXF3CGAF +slack-channel: &slack-channel C0421KHNAV9 #feed-consul-k8s-ci channel ID control-plane-path: &control-plane-path control-plane cli-path: &cli-path cli acceptance-mod-path: &acceptance-mod-path acceptance From 67d75bdf317cdba6eccf19fa536c82a36c9f1581 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 12 Sep 2022 16:04:04 -0400 Subject: [PATCH 120/235] Make CNI tests dependent on non-CNI tests passing (#1495) --- .circleci/config.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f09a2f1877..234ed85af5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1254,24 +1254,21 @@ workflows: - dev-upload-docker - acceptance-gke-cni-1-23: requires: - - cleanup-gcp-resources - - dev-upload-docker + - acceptance-gke-1-23 - acceptance-eks-1-21: requires: - cleanup-eks-resources - dev-upload-docker - acceptance-eks-cni-1-21: requires: - - cleanup-eks-resources - - dev-upload-docker + - acceptance-eks-1-21 - acceptance-aks-1-22: requires: - cleanup-azure-resources - dev-upload-docker - acceptance-aks-cni-1-22: requires: - - cleanup-azure-resources - - dev-upload-docker + - acceptance-aks-1-22 nightly-acceptance-tests-consul: triggers: From a448a755dfd5590bc4d944f53f6da176af070207 Mon Sep 17 00:00:00 2001 From: John Murret Date: Tue, 13 Sep 2022 13:11:39 -0600 Subject: [PATCH 121/235] Rolling back helm upgrade in CLI back to 3.6.1 (#1492) * Revert "Bump helm.sh/helm/v3 from 3.6.1 to 3.9.4 in /cli (#1465)" This reverts commit beff736456c330801882f5c0b80e766005b4e267. * run nightlies on this branch * removing changes to circleci config --- cli/go.mod | 165 ++++----- cli/go.sum | 1028 +++++++++++++++++++++++++--------------------------- 2 files changed, 574 insertions(+), 619 deletions(-) diff --git a/cli/go.mod b/cli/go.mod index f130971e0a..00c718a139 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -5,155 +5,158 @@ go 1.18 require ( github.com/bgentry/speakeasy v0.1.0 github.com/cenkalti/backoff v2.2.1+incompatible - github.com/fatih/color v1.13.0 - github.com/google/go-cmp v0.5.6 + github.com/fatih/color v1.9.0 + github.com/google/go-cmp v0.5.5 github.com/hashicorp/consul-k8s/charts v0.0.0-00010101000000-000000000000 github.com/hashicorp/go-hclog v0.16.2 github.com/kr/text v0.2.0 - github.com/mattn/go-isatty v0.0.14 + github.com/mattn/go-isatty v0.0.12 github.com/mitchellh/cli v1.1.2 - github.com/olekukonko/tablewriter v0.0.5 + github.com/olekukonko/tablewriter v0.0.4 github.com/posener/complete v1.1.1 - github.com/stretchr/testify v1.7.2 - helm.sh/helm/v3 v3.9.4 - k8s.io/api v0.24.2 - k8s.io/apimachinery v0.24.2 - k8s.io/cli-runtime v0.24.2 - k8s.io/client-go v0.24.2 - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 - sigs.k8s.io/yaml v1.3.0 + github.com/stretchr/testify v1.7.0 + helm.sh/helm/v3 v3.6.1 + k8s.io/api v0.22.2 + k8s.io/apimachinery v0.22.2 + k8s.io/cli-runtime v0.21.0 + k8s.io/client-go v0.22.2 + k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a + sigs.k8s.io/yaml v1.2.0 ) require ( - cloud.google.com/go v0.99.0 // indirect + cloud.google.com/go v0.54.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.24 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.18 // indirect + github.com/Azure/go-autorest/autorest v0.11.18 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/BurntSushi/toml v1.0.0 // indirect + github.com/BurntSushi/toml v0.3.1 // indirect github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/Masterminds/squirrel v1.5.3 // indirect + github.com/Masterminds/squirrel v1.5.0 // indirect + github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/hcsshim v0.8.14 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect - github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect - github.com/containerd/containerd v1.6.6 // indirect - github.com/cyphar/filepath-securejoin v0.2.3 // indirect + github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 // indirect + github.com/containerd/containerd v1.4.4 // indirect + github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 // indirect + github.com/cyphar/filepath-securejoin v0.2.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/docker/cli v20.10.17+incompatible // indirect - github.com/docker/distribution v2.8.1+incompatible // indirect - github.com/docker/docker v20.10.17+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.4 // indirect + github.com/deislabs/oras v0.11.1 // indirect + github.com/docker/cli v20.10.5+incompatible // indirect + github.com/docker/distribution v2.7.1+incompatible // indirect + github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible // indirect + github.com/docker/docker-credential-helpers v0.6.3 // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-metrics v0.0.1 // indirect + github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect - github.com/evanphx/json-patch v4.12.0+incompatible // indirect + github.com/evanphx/json-patch v4.11.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect + github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect github.com/go-errors/errors v1.0.1 // indirect - github.com/go-gorp/gorp/v3 v3.0.2 // indirect - github.com/go-logr/logr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect + github.com/go-logr/logr v0.4.0 // indirect + github.com/go-openapi/jsonpointer v0.19.3 // indirect + github.com/go-openapi/jsonreference v0.19.3 // indirect + github.com/go-openapi/spec v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang-jwt/jwt/v4 v4.2.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/gofuzz v1.2.0 // indirect + github.com/google/gofuzz v1.1.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.2.0 // indirect - github.com/gorilla/mux v1.8.0 // indirect + github.com/google/uuid v1.1.2 // indirect + github.com/googleapis/gnostic v0.5.5 // indirect + github.com/gorilla/mux v1.7.3 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect + github.com/hashicorp/errwrap v1.0.0 // indirect + github.com/hashicorp/go-multierror v1.1.0 // indirect github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/imdario/mergo v0.3.11 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jmoiron/sqlx v1.3.5 // indirect + github.com/jmoiron/sqlx v1.3.1 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.13.6 // indirect + github.com/json-iterator/go v1.1.11 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/lib/pq v1.10.6 // indirect + github.com/lib/pq v1.10.0 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-colorable v0.1.12 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-colorable v0.1.8 // indirect + github.com/mattn/go-runewidth v0.0.7 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/copystructure v1.1.1 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/moby/locker v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/modern-go/reflect2 v1.0.1 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect + github.com/opencontainers/image-spec v1.0.1 // indirect + github.com/opencontainers/runc v0.1.1 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.12.1 // indirect + github.com/prometheus/client_golang v1.11.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect - github.com/rubenv/sql-migrate v1.1.1 // indirect + github.com/prometheus/common v0.26.0 // indirect + github.com/prometheus/procfs v0.6.0 // indirect + github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 // indirect github.com/russross/blackfriday v1.5.2 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/spf13/cast v1.4.1 // indirect - github.com/spf13/cobra v1.4.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/cobra v1.1.3 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect + go.opencensus.io v0.22.3 // indirect go.starlark.net v0.0.0-20200707032745-474f21a9602d // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect + golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect + golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect + golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect + golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect + golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 // indirect - google.golang.org/grpc v1.43.0 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect + google.golang.org/appengine v1.6.5 // indirect + google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect + google.golang.org/grpc v1.36.0 // indirect google.golang.org/protobuf v1.27.1 // indirect + gopkg.in/gorp.v1 v1.7.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.24.2 // indirect - k8s.io/apiserver v0.24.2 // indirect - k8s.io/component-base v0.24.2 // indirect - k8s.io/klog/v2 v2.60.1 // indirect - k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 // indirect - k8s.io/kubectl v0.24.2 // indirect - oras.land/oras-go v1.2.0 // indirect - sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect - sigs.k8s.io/kustomize/api v0.11.4 // indirect - sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect + gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + k8s.io/apiextensions-apiserver v0.21.0 // indirect + k8s.io/apiserver v0.21.0 // indirect + k8s.io/component-base v0.21.0 // indirect + k8s.io/klog/v2 v2.9.0 // indirect + k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect + k8s.io/kubectl v0.21.0 // indirect + rsc.io/letsencrypt v0.0.3 // indirect + sigs.k8s.io/kustomize/api v0.8.5 // indirect + sigs.k8s.io/kustomize/kyaml v0.10.15 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect ) // This replace directive is to avoid having to manually bump the version of the charts module upon changes to the Helm diff --git a/cli/go.sum b/cli/go.sum index 13d8d9c526..d65d9b4ff1 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -1,3 +1,4 @@ +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -8,67 +9,50 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= +github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest v0.11.24 h1:1fIGgHKqVm54KIPT+q8Zmd1QlVsmHqeUGso5qm2BqqE= -github.com/Azure/go-autorest/autorest v0.11.24/go.mod h1:G6kyRlFnTuSbEYkQGawPfsCswgme4iYf6rfSKUDzbCc= +github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/adal v0.9.18 h1:kLnPsRjzZZUF3K5REu/Kc+qMQrvuza2bwSnNdhmzLfQ= -github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= -github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -82,208 +66,284 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= -github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= -github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= +github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/Y8cY8= +github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= +github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns= +github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= +github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= -github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= -github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= -github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= -github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= -github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= -github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0= -github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk= +github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= +github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= +github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= +github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= +github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= +github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= +github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= +github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= +github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= -github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= +github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= +github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/deislabs/oras v0.11.1 h1:oo2J/3vXdcti8cjFi8ghMOkx0OacONxHC8dhJ17NdJ0= +github.com/deislabs/oras v0.11.1/go.mod h1:39lCtf8Q6WDC7ul9cnyWXONNzKvabEKk+AX+L0ImnQk= +github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269 h1:hbCT8ZPPMqefiAWD2ZKjn7ypokIGViTvBBg/ExLSdCk= -github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= -github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= -github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= -github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= -github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= +github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE= +github.com/docker/cli v20.10.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= +github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= +github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8= +github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= +github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= -github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= -github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= -github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= -github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= +github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gorp/gorp/v3 v3.0.2 h1:ULqJXIekoqMx29FI5ekXXFoH1dT2Vc8UhnRzBg+Emz4= -github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY= +github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= +github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= +github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= +github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= +github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= +github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= +github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= +github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= +github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= +github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= +github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= +github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= +github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= +github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= +github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= +github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= +github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= +github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= +github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= +github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= +github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= +github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw= +github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= +github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= +github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= +github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= +github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= +github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= +github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= +github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= +github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= -github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= -github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= -github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= -github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= -github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= -github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= +github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= +github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= +github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg= +github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o= +github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= +github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= +github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= -github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -295,16 +355,11 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -314,99 +369,85 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= -github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= -github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w= -github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= +github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= +github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= -github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= -github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -419,50 +460,48 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= -github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE= +github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= -github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= -github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -471,41 +510,43 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtB github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= -github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= -github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= -github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= -github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= -github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= -github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= +github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= +github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= +github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -516,8 +557,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4= +github.com/mitchellh/copystructure v1.1.1/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -528,153 +569,202 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= +github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= +github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= +github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= +github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= +github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= -github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= -github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= +github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= -github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +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= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1 h1:oL4IBbcqwhhNWh31bjOX8C/OCy0zs9906d/VUru+bqg= -github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY= -github.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.4.0 h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY= +github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 h1:HXr/qUllAWv9riaI4zh2eXWKmCSDqVS/XH1MRHLKRwk= +github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= -github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= +github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= +github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= -github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= -github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -684,12 +774,18 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= @@ -699,78 +795,64 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= -go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0= -go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q= -go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE= -go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc= -go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= +go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= -go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= -go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= -go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= -go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= -go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= -go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= -go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= -go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.starlark.net v0.0.0-20200707032745-474f21a9602d h1:uFqwFYlX7d5ZSp+IqhXxct0SybXrTzEBDvb2CkEhPBs= go.starlark.net v0.0.0-20200707032745-474f21a9602d/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= +golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -793,8 +875,6 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -803,29 +883,32 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -833,63 +916,29 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= +golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -897,102 +946,86 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= +golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1002,13 +1035,17 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1017,6 +1054,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1024,38 +1062,18 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= -golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1065,41 +1083,21 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1112,80 +1110,27 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368 h1:Et6SkiuvnBn+SgrSYXs/BrUpGB4mbdwt4R3vaPIlicA= -google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= +google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM= -google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1202,99 +1147,106 @@ google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+Rur google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= +gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= +gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -helm.sh/helm/v3 v3.9.4 h1:TCI1QhJUeLVOdccfdw+vnSEO3Td6gNqibptB04QtExY= -helm.sh/helm/v3 v3.9.4/go.mod h1:3eaWAIqzvlRSD06gR9MMwmp2KBKwlu9av1/1BZpjeWY= +helm.sh/helm/v3 v3.6.1 h1:TQ6q4pAatXr7qh2fbLcb0oNd0I3J7kv26oo5cExKTtc= +helm.sh/helm/v3 v3.6.1/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.24.2 h1:g518dPU/L7VRLxWfcadQn2OnsiGWVOadTLpdnqgY2OI= -k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= -k8s.io/apiextensions-apiserver v0.24.2 h1:/4NEQHKlEz1MlaK/wHT5KMKC9UKYz6NZz6JE6ov4G6k= -k8s.io/apiextensions-apiserver v0.24.2/go.mod h1:e5t2GMFVngUEHUd0wuCJzw8YDwZoqZfJiGOW6mm2hLQ= -k8s.io/apimachinery v0.24.2 h1:5QlH9SL2C8KMcrNJPor+LbXVTaZRReml7svPEh4OKDM= -k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= -k8s.io/apiserver v0.24.2 h1:orxipm5elPJSkkFNlwH9ClqaKEDJJA3yR2cAAlCnyj4= -k8s.io/apiserver v0.24.2/go.mod h1:pSuKzr3zV+L+MWqsEo0kHHYwCo77AT5qXbFXP2jbvFI= -k8s.io/cli-runtime v0.24.2 h1:KxY6tSgPGsahA6c1/dmR3uF5jOxXPx2QQY6C5ZrLmtE= -k8s.io/cli-runtime v0.24.2/go.mod h1:1LIhKL2RblkhfG4v5lZEt7FtgFG5mVb8wqv5lE9m5qY= -k8s.io/client-go v0.24.2 h1:CoXFSf8if+bLEbinDqN9ePIDGzcLtqhfd6jpfnwGOFA= -k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= -k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= -k8s.io/component-base v0.24.2 h1:kwpQdoSfbcH+8MPN4tALtajLDfSfYxBDYlXobNWI6OU= -k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM= -k8s.io/component-helpers v0.24.2/go.mod h1:TRQPBQKfmqkmV6c0HAmUs8cXVNYYYLsXy4zu8eODi9g= +k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= +k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= +k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= +k8s.io/apiextensions-apiserver v0.21.0 h1:Nd4uBuweg6ImzbxkC1W7xUNZcCV/8Vt10iTdTIVF3hw= +k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc= +k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= +k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= +k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= +k8s.io/apiserver v0.21.0 h1:1hWMfsz+cXxB77k6/y0XxWxwl6l9OF26PC9QneUVn1Q= +k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= +k8s.io/cli-runtime v0.21.0 h1:/V2Kkxtf6x5NI2z+Sd/mIrq4FQyQ8jzZAUD6N5RnN7Y= +k8s.io/cli-runtime v0.21.0/go.mod h1:XoaHP93mGPF37MkLbjGVYqg3S1MnsFdKtiA/RZzzxOo= +k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= +k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= +k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= +k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= +k8s.io/component-base v0.21.0 h1:tLLGp4BBjQaCpS/KiuWh7m2xqvAdsxLm4ATxHSe5Zpg= +k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw= +k8s.io/component-helpers v0.21.0/go.mod h1:tezqefP7lxfvJyR+0a+6QtVrkZ/wIkyMLK4WcQ3Cj8U= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc= -k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= +k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= +k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= +k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= -k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8 h1:yEQKdMCjzAOvGeiTwG4hO/hNVNtDOuUFvMUZ0OlaIzs= -k8s.io/kube-openapi v0.0.0-20220627174259-011e075b9cb8/go.mod h1:mbJ+NSUoAhuR14N0S63bPkh8MGVSo3VYSGZtH/mfMe0= -k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= -k8s.io/kubectl v0.24.2/go.mod h1:+HIFJc0bA6Tzu5O/YcuUt45APAxnNL8LeMuXwoiGsPg= -k8s.io/metrics v0.24.2/go.mod h1:5NWURxZ6Lz5gj8TFU83+vdWIVASx7W8lwPpHYCqopMo= -k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc= -k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -oras.land/oras-go v1.2.0 h1:yoKosVIbsPoFMqAIFHTnrmOuafHal+J/r+I5bdbVWu4= -oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc= +k8s.io/kubectl v0.21.0 h1:WZXlnG/yjcE4LWO2g6ULjFxtzK6H1TKzsfaBFuVIhNg= +k8s.io/kubectl v0.21.0/go.mod h1:EU37NukZRXn1TpAkMUoy8Z/B2u6wjHDS4aInsDzVvks= +k8s.io/metrics v0.21.0/go.mod h1:L3Ji9EGPP1YBbfm9sPfEXSpnj8i24bfQbAFAsW0NueQ= +k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= +k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= +rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 h1:kDi4JBNAsJWfz1aEXhO8Jg87JJaPNLh5tIzYHgStQ9Y= -sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= -sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= -sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= -sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= -sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= -sigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs= -sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= +sigs.k8s.io/kustomize/api v0.8.5 h1:bfCXGXDAbFbb/Jv5AhMj2BB8a5VAJuuQ5/KU69WtDjQ= +sigs.k8s.io/kustomize/api v0.8.5/go.mod h1:M377apnKT5ZHJS++6H4rQoCHmWtt6qTpp3mbe7p6OLY= +sigs.k8s.io/kustomize/cmd/config v0.9.7/go.mod h1:MvXCpHs77cfyxRmCNUQjIqCmZyYsbn5PyQpWiq44nW0= +sigs.k8s.io/kustomize/kustomize/v4 v4.0.5/go.mod h1:C7rYla7sI8EnxHE/xEhRBSHMNfcL91fx0uKmUlUhrBk= +sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI= +sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y= -sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= +sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From 47e9faea508dedc09ac9116f070f6d7d0a3e1bcc Mon Sep 17 00:00:00 2001 From: John Murret Date: Thu, 15 Sep 2022 13:59:19 -0600 Subject: [PATCH 122/235] pin vault helm chart version to v0.21.0 in Acceptance tests (#1499) * pin vault helm chart version to v0.21.0 --- acceptance/framework/vault/vault_cluster.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/acceptance/framework/vault/vault_cluster.go b/acceptance/framework/vault/vault_cluster.go index 3710617fa7..c8105fa806 100644 --- a/acceptance/framework/vault/vault_cluster.go +++ b/acceptance/framework/vault/vault_cluster.go @@ -24,7 +24,8 @@ import ( ) const ( - releaseLabel = "app.kubernetes.io/instance=" + releaseLabel = "app.kubernetes.io/instance=" + defaultVaultHelmChartVersion = "v0.21.0" ) // VaultCluster represents a vault installation. @@ -61,6 +62,7 @@ func NewVaultCluster(t *testing.T, ctx environment.TestContext, cfg *config.Test SetValues: values, KubectlOptions: kopts, Logger: logger, + Version: defaultVaultHelmChartVersion, } helm.AddRepo(t, vaultHelmOpts, "hashicorp", "https://helm.releases.hashicorp.com") From c06de03186b4a36b6afa9eaa19b048065814bc39 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Tue, 13 Sep 2022 15:32:48 -0700 Subject: [PATCH 123/235] add target to makefile --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6edb9b79e3..9d30251581 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,11 @@ kind-cni: # ===========> CLI Targets +cli-dev: + @echo "==> Installing consul-k8s CLI tool for ${GOOS}/${GOARCH}" + @cd cli; go build -o ./bin/consul-k8s; cp ./bin/consul-k8s ${GOPATH}/bin/ + + cli-lint: ## Run linter in the control-plane directory. cd cli; golangci-lint run -c ../.golangci.yml @@ -144,7 +149,7 @@ endif # ===========> Makefile config .DEFAULT_GOAL := help -.PHONY: gen-helm-docs copy-crds-to-chart bats-tests help ci.aws-acceptance-test-cleanup version +.PHONY: gen-helm-docs copy-crds-to-chart bats-tests help ci.aws-acceptance-test-cleanup version cli-dev SHELL = bash GOOS?=$(shell go env GOOS) GOARCH?=$(shell go env GOARCH) From a7ada7d546ea2080fd9a43e525758ed1a71243e9 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Wed, 14 Sep 2022 14:31:56 -0700 Subject: [PATCH 124/235] update Contributing.md --- CONTRIBUTING.md | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c9107cf11e..ec825cafd2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -108,23 +108,17 @@ helm install consul --create-namespace -n consul -f ./values.dev.yaml ./charts/c ### Building and running the `consul-k8s` CLI -Change directory into the `cli` folder where the golang code resides. +Compile the `consul-k8s` CLI binary for your local machine: ```shell -cd cli +make cli-dev ``` +This will compile the `consul-k8s` binary into `cli/bin/consul-k8s` as well as your `$GOPATH`. -Build the CLI binary using the following command +Run the CLI as follows: ```shell -go build -o bin/consul-k8s -``` - -Run the CLI as follows - -```shell -./bin/consul-k8s version -consul-k8s 0.36.0-dev +consul-k8s version ``` ### Making changes to consul-k8s From d9de5f1418d2d6dbf097667c0cbee603316316bb Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Thu, 15 Sep 2022 20:30:25 -0400 Subject: [PATCH 125/235] server-acl-init: Create global ACL auth method for API Gateway in secondary dc (#1481) * server-acl-init: Use global policy + auth method for API Gateway in secondary dc * Update test assertions to expect global auth method + token * Add changelog entry * Update control-plane/subcommand/server-acl-init/command.go Co-authored-by: Mike Morris * Update CHANGELOG.md Co-authored-by: Kyle Schochenmaier Co-authored-by: Mike Morris Co-authored-by: Kyle Schochenmaier --- CHANGELOG.md | 4 ++++ control-plane/subcommand/server-acl-init/command.go | 11 ++++++++++- .../subcommand/server-acl-init/command_test.go | 6 +++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0090c797bc..75b5cce974 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +BUG FIXES: +* Control plane + * Use global ACL auth method to provision ACL tokens for API Gateway in secondary datacenter [[GH-1481](https://github.com/hashicorp/consul-k8s/pull/1481)] + ## 0.48.0 (September 01, 2022) FEATURES: diff --git a/control-plane/subcommand/server-acl-init/command.go b/control-plane/subcommand/server-acl-init/command.go index 69a98a28d8..9f54feac20 100644 --- a/control-plane/subcommand/server-acl-init/command.go +++ b/control-plane/subcommand/server-acl-init/command.go @@ -592,7 +592,16 @@ func (c *Command) Run(args []string) int { return 1 } serviceAccountName := c.withPrefix("api-gateway-controller") - if err := c.createACLPolicyRoleAndBindingRule("api-gateway-controller", rules, consulDC, primaryDC, localPolicy, primary, localComponentAuthMethodName, serviceAccountName, consulClient); err != nil { + + // API gateways require a global policy/token because they must + // create config-entry resources in the primary, even when deployed + // to a secondary datacenter + authMethodName := localComponentAuthMethodName + if !primary { + authMethodName = globalComponentAuthMethodName + } + err = c.createACLPolicyRoleAndBindingRule("api-gateway-controller", rules, consulDC, primaryDC, globalPolicy, primary, authMethodName, serviceAccountName, consulClient) + if err != nil { c.log.Error(err.Error()) return 1 } diff --git a/control-plane/subcommand/server-acl-init/command_test.go b/control-plane/subcommand/server-acl-init/command_test.go index a89fbe2328..83fa50b3b7 100644 --- a/control-plane/subcommand/server-acl-init/command_test.go +++ b/control-plane/subcommand/server-acl-init/command_test.go @@ -2291,7 +2291,7 @@ func TestRun_PoliciesAndBindingRulesACLLogin_SecondaryDatacenter(t *testing.T) { TokenFlags: []string{"-api-gateway-controller"}, PolicyNames: []string{"api-gateway-controller-policy-" + secondaryDatacenter}, Roles: []string{resourcePrefix + "-api-gateway-controller-acl-role-" + secondaryDatacenter}, - GlobalAuthMethod: false, + GlobalAuthMethod: true, }, { TestName: "Snapshot Agent", @@ -2599,8 +2599,8 @@ func TestRun_ValidateLoginToken_SecondaryDatacenter(t *testing.T) { ComponentName: "api-gateway-controller", TokenFlags: []string{"-api-gateway-controller"}, Roles: []string{resourcePrefix + "-api-gateway-controller-acl-role-dc2"}, - GlobalAuthMethod: false, - GlobalToken: false, + GlobalAuthMethod: true, + GlobalToken: true, }, { ComponentName: "snapshot-agent", From c71c13f07c24152c21674a28a93a7e211f2ca5b4 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Fri, 16 Sep 2022 12:03:29 -0700 Subject: [PATCH 126/235] ci: add backport pipeline (#1489) * add backport pipeline * added automerge - This will automatically merge backported changes without creating a PR if there are no errors. If there are errors (merge conflicts, failure to cherrypick, etc.), then a PR will be created requiring manual intervention to resolve * added a token with elevated permissions Co-authored-by: Michael Wilkerson --- .github/workflows/backport.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/backport.yml diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 0000000000..c1548332e0 --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,21 @@ +--- +name: Backport Assistant Runner + +on: + pull_request: + types: + - closed + - labeled + +jobs: + backport: + if: github.event.pull_request.merged + runs-on: ubuntu-latest + container: hashicorpdev/backport-assistant:0.2.5 + steps: + - name: Run Backport Assistant + run: backport-assistant backport -automerge + env: + BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+\\.x)" + BACKPORT_TARGET_TEMPLATE: "release/{{.target}}" + GITHUB_TOKEN: ${{ secrets.ELEVATED_GITHUB_TOKEN }} From ed26be7d374ab4c7dbf7c463e852d4d38a0f3ce6 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Fri, 16 Sep 2022 12:03:48 -0700 Subject: [PATCH 127/235] Add cli autocomplete (#1501) * enable autocomplete * add auto-completions - add AutocompleteFlags() and AutocompleteArgs() to commands to adhere to autocomplete interface - add variables for command flag names where necessary - deleted some unused arguments - refactored some naming package/variable naming collisions * add cli autocomplete tests * fixed some linter errors in set * update changelog --- CHANGELOG.md | 4 ++ cli/cmd/install/install.go | 50 ++++++++++++++++++---- cli/cmd/install/install_test.go | 35 ++++++++++++++++ cli/cmd/proxy/command.go | 2 +- cli/cmd/proxy/list/command.go | 36 ++++++++++++++-- cli/cmd/proxy/list/command_test.go | 37 ++++++++++++++++ cli/cmd/proxy/read/command.go | 65 +++++++++++++++++++++++------ cli/cmd/proxy/read/command_test.go | 36 ++++++++++++++++ cli/cmd/status/status.go | 27 +++++++++++- cli/cmd/status/status_test.go | 34 +++++++++++++++ cli/cmd/uninstall/uninstall.go | 34 +++++++++++++-- cli/cmd/uninstall/uninstall_test.go | 37 +++++++++++++++- cli/cmd/upgrade/upgrade.go | 35 +++++++++++++++- cli/cmd/upgrade/upgrade_test.go | 35 ++++++++++++++++ cli/common/flag/set.go | 43 +++++++++---------- cli/main.go | 3 ++ 16 files changed, 457 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75b5cce974..39fdbdbf5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +FEATURES: +* CLI: + * Add support for tab autocompletion [[GH-1437](https://github.com/hashicorp/consul-k8s/pull/1501)] + BUG FIXES: * Control plane * Use global ACL auth method to provision ACL tokens for API Gateway in secondary datacenter [[GH-1481](https://github.com/hashicorp/consul-k8s/pull/1481)] diff --git a/cli/cmd/install/install.go b/cli/cmd/install/install.go index 3329c6fc58..61742cebbe 100644 --- a/cli/cmd/install/install.go +++ b/cli/cmd/install/install.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/consul-k8s/cli/helm" "github.com/hashicorp/consul-k8s/cli/release" "github.com/hashicorp/consul-k8s/cli/validation" + "github.com/posener/complete" "helm.sh/helm/v3/pkg/action" helmCLI "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/cli/values" @@ -52,6 +53,9 @@ const ( flagNameWait = "wait" defaultWait = true + + flagNameContext = "context" + flagNameKubeconfig = "kubeconfig" ) type Command struct { @@ -158,14 +162,14 @@ func (c *Command) init() { f = c.set.NewSet("Global Options") f.StringVar(&flag.StringVar{ - Name: "kubeconfig", + Name: flagNameKubeconfig, Aliases: []string{"c"}, Target: &c.flagKubeConfig, Default: "", Usage: "Set the path to kubeconfig file.", }) f.StringVar(&flag.StringVar{ - Name: "context", + Name: flagNameContext, Target: &c.flagKubeContext, Default: "", Usage: "Set the Kubernetes context to use.", @@ -265,20 +269,20 @@ func (c *Command) Run(args []string) int { return 1 } - var values helm.Values - err = yaml.Unmarshal(valuesYaml, &values) + var helmVals helm.Values + err = yaml.Unmarshal(valuesYaml, &helmVals) if err != nil { c.UI.Output(err.Error(), terminal.WithErrorStyle()) return 1 } - release := release.Release{ + rel := release.Release{ Name: "consul", Namespace: c.flagNamespace, - Configuration: values, + Configuration: helmVals, } - msg, err := c.checkForPreviousSecrets(release) + msg, err := c.checkForPreviousSecrets(rel) if err != nil { c.UI.Output(err.Error(), terminal.WithErrorStyle()) return 1 @@ -286,8 +290,8 @@ func (c *Command) Run(args []string) int { c.UI.Output(msg, terminal.WithSuccessStyle()) // If an enterprise license secret was provided, check that the secret exists and that the enterprise Consul image is set. - if values.Global.EnterpriseLicense.SecretName != "" { - if err := c.checkValidEnterprise(release.Configuration.Global.EnterpriseLicense.SecretName); err != nil { + if helmVals.Global.EnterpriseLicense.SecretName != "" { + if err := c.checkValidEnterprise(rel.Configuration.Global.EnterpriseLicense.SecretName); err != nil { c.UI.Output(err.Error(), terminal.WithErrorStyle()) return 1 } @@ -383,6 +387,34 @@ func (c *Command) Synopsis() string { return "Install Consul on Kubernetes." } +// AutocompleteFlags returns a mapping of supported flags and autocomplete +// options for this command. The map key for the Flags map should be the +// complete flag such as "-foo" or "--foo". +func (c *Command) AutocompleteFlags() complete.Flags { + return complete.Flags{ + fmt.Sprintf("-%s", flagNamePreset): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameNamespace): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameDryRun): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameAutoApprove): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameConfigFile): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameSetStringValues): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameSetValues): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameFileValues): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameTimeout): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameVerbose): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameWait): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameContext): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameKubeconfig): complete.PredictNothing, + } +} + +// AutocompleteArgs returns the argument predictor for this command. +// Since argument completion is not supported, this will return +// complete.PredictNothing. +func (c *Command) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + // checkForPreviousPVCs checks for existing Kubernetes persistent volume claims with a name containing "consul-server" // and returns an error with a list of PVCs it finds if any match. func (c *Command) checkForPreviousPVCs() error { diff --git a/cli/cmd/install/install_test.go b/cli/cmd/install/install_test.go index 4bbe518932..a66febc336 100644 --- a/cli/cmd/install/install_test.go +++ b/cli/cmd/install/install_test.go @@ -2,13 +2,18 @@ package install import ( "context" + "flag" + "fmt" "os" "testing" "github.com/hashicorp/consul-k8s/cli/common" + cmnFlag "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/helm" "github.com/hashicorp/consul-k8s/cli/release" "github.com/hashicorp/go-hclog" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -248,3 +253,33 @@ func TestCheckValidEnterprise(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "please make sure that the secret exists") } + +func TestTaskCreateCommand_AutocompleteFlags(t *testing.T) { + t.Parallel() + cmd := getInitializedCommand(t) + + predictor := cmd.AutocompleteFlags() + + // Test that we get the expected number of predictions + args := complete.Args{Last: "-"} + res := predictor.Predict(args) + + // Grab the list of flags from the Flag object + flags := make([]string, 0) + cmd.set.VisitSets(func(name string, set *cmnFlag.Set) { + set.VisitAll(func(flag *flag.Flag) { + flags = append(flags, fmt.Sprintf("-%s", flag.Name)) + }) + }) + + // Verify that there is a prediction for each flag associated with the command + assert.Equal(t, len(flags), len(res)) + assert.ElementsMatch(t, flags, res, "flags and predictions didn't match, make sure to add "+ + "new flags to the command AutoCompleteFlags function") +} + +func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { + cmd := getInitializedCommand(t) + c := cmd.AutocompleteArgs() + assert.Equal(t, complete.PredictNothing, c) +} diff --git a/cli/cmd/proxy/command.go b/cli/cmd/proxy/command.go index 663893de5e..bc55ee0312 100644 --- a/cli/cmd/proxy/command.go +++ b/cli/cmd/proxy/command.go @@ -13,7 +13,7 @@ type ProxyCommand struct { } // Run prints out information about the subcommands. -func (c *ProxyCommand) Run(args []string) int { +func (c *ProxyCommand) Run([]string) int { return cli.RunResultHelp } diff --git a/cli/cmd/proxy/list/command.go b/cli/cmd/proxy/list/command.go index 780a376a0f..cbecda79a1 100644 --- a/cli/cmd/proxy/list/command.go +++ b/cli/cmd/proxy/list/command.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/consul-k8s/cli/common" "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/common/terminal" + "github.com/posener/complete" helmCLI "helm.sh/helm/v3/pkg/cli" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/validation" @@ -16,6 +17,13 @@ import ( "k8s.io/client-go/kubernetes" ) +const ( + flagNameNamespace = "namespace" + flagNameAllNamespaces = "all-namespaces" + flagNameKubeConfig = "kubeconfig" + flagNameKubeContext = "context" +) + // ListCommand is the command struct for the proxy list command. type ListCommand struct { *common.BaseCommand @@ -40,13 +48,13 @@ func (c *ListCommand) init() { f := c.set.NewSet("Command Options") f.StringVar(&flag.StringVar{ - Name: "namespace", + Name: flagNameNamespace, Target: &c.flagNamespace, Usage: "The namespace to list proxies in.", Aliases: []string{"n"}, }) f.BoolVar(&flag.BoolVar{ - Name: "all-namespaces", + Name: flagNameAllNamespaces, Target: &c.flagAllNamespaces, Default: false, Usage: "List pods in all namespaces.", @@ -55,14 +63,14 @@ func (c *ListCommand) init() { f = c.set.NewSet("Global Options") f.StringVar(&flag.StringVar{ - Name: "kubeconfig", + Name: flagNameKubeConfig, Aliases: []string{"c"}, Target: &c.flagKubeConfig, Default: "", Usage: "Set the path to kubeconfig file.", }) f.StringVar(&flag.StringVar{ - Name: "context", + Name: flagNameKubeContext, Target: &c.flagKubeContext, Default: "", Usage: "Set the Kubernetes context to use.", @@ -117,6 +125,25 @@ func (c *ListCommand) Synopsis() string { return "List all Pods running proxies managed by Consul." } +// AutocompleteFlags returns a mapping of supported flags and autocomplete +// options for this command. The map key for the Flags map should be the +// complete flag such as "-foo" or "--foo". +func (c *ListCommand) AutocompleteFlags() complete.Flags { + return complete.Flags{ + fmt.Sprintf("-%s", flagNameNamespace): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameAllNamespaces): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameKubeConfig): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameKubeContext): complete.PredictNothing, + } +} + +// AutocompleteArgs returns the argument predictor for this command. +// Since argument completion is not supported, this will return +// complete.PredictNothing. +func (c *ListCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + // validateFlags ensures that the flags passed in by the can be used. func (c *ListCommand) validateFlags() error { if len(c.set.Args()) > 0 { @@ -125,6 +152,7 @@ func (c *ListCommand) validateFlags() error { if errs := validation.ValidateNamespaceName(c.flagNamespace, false); c.flagNamespace != "" && len(errs) > 0 { return fmt.Errorf("invalid namespace name passed for -namespace/-n: %v", strings.Join(errs, "; ")) } + return nil } diff --git a/cli/cmd/proxy/list/command_test.go b/cli/cmd/proxy/list/command_test.go index a29c851391..b2c2cb6043 100644 --- a/cli/cmd/proxy/list/command_test.go +++ b/cli/cmd/proxy/list/command_test.go @@ -3,13 +3,18 @@ package list import ( "bytes" "context" + "flag" + "fmt" "io" "os" "testing" "github.com/hashicorp/consul-k8s/cli/common" + cmnFlag "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/go-hclog" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -359,3 +364,35 @@ func setupCommand(buf io.Writer) *ListCommand { return command } + +func TestTaskCreateCommand_AutocompleteFlags(t *testing.T) { + t.Parallel() + buf := new(bytes.Buffer) + cmd := setupCommand(buf) + + predictor := cmd.AutocompleteFlags() + + // Test that we get the expected number of predictions + args := complete.Args{Last: "-"} + res := predictor.Predict(args) + + // Grab the list of flags from the Flag object + flags := make([]string, 0) + cmd.set.VisitSets(func(name string, set *cmnFlag.Set) { + set.VisitAll(func(flag *flag.Flag) { + flags = append(flags, fmt.Sprintf("-%s", flag.Name)) + }) + }) + + // Verify that there is a prediction for each flag associated with the command + assert.Equal(t, len(flags), len(res)) + assert.ElementsMatch(t, flags, res, "flags and predictions didn't match, make sure to add "+ + "new flags to the command AutoCompleteFlags function") +} + +func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { + buf := new(bytes.Buffer) + cmd := setupCommand(buf) + c := cmd.AutocompleteArgs() + assert.Equal(t, complete.PredictNothing, c) +} diff --git a/cli/cmd/proxy/read/command.go b/cli/cmd/proxy/read/command.go index 4123f70adb..ad2bb96303 100644 --- a/cli/cmd/proxy/read/command.go +++ b/cli/cmd/proxy/read/command.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/consul-k8s/cli/common" "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/common/terminal" + "github.com/posener/complete" helmCLI "helm.sh/helm/v3/pkg/cli" "k8s.io/apimachinery/pkg/api/validation" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -25,6 +26,19 @@ const ( Table = "table" JSON = "json" Raw = "raw" + + flagNameNamespace = "namespace" + flagNameOutput = "output" + flagNameClusters = "clusters" + flagNameListeners = "listeners" + flagNameRoutes = "routes" + flagNameEndpoints = "endpoints" + flagNameSecrets = "secrets" + flagNameFQDN = "fqdn" + flagNameAddress = "address" + flagNamePort = "port" + flagNameKubeConfig = "kubeconfig" + flagNameKubeContext = "context" ) type ReadCommand struct { @@ -69,13 +83,13 @@ func (c *ReadCommand) init() { c.set = flag.NewSets() f := c.set.NewSet("Command Options") f.StringVar(&flag.StringVar{ - Name: "namespace", + Name: flagNameNamespace, Target: &c.flagNamespace, Usage: "The namespace where the target Pod can be found.", Aliases: []string{"n"}, }) f.StringVar(&flag.StringVar{ - Name: "output", + Name: flagNameOutput, Target: &c.flagOutput, Usage: "Output the Envoy configuration as 'table', 'json', or 'raw'.", Default: Table, @@ -84,42 +98,42 @@ func (c *ReadCommand) init() { f = c.set.NewSet("Output Filtering Options") f.BoolVar(&flag.BoolVar{ - Name: "clusters", + Name: flagNameClusters, Target: &c.flagClusters, Usage: "Filter output to only show clusters.", }) f.BoolVar(&flag.BoolVar{ - Name: "listeners", + Name: flagNameListeners, Target: &c.flagListeners, Usage: "Filter output to only show listeners.", }) f.BoolVar(&flag.BoolVar{ - Name: "routes", + Name: flagNameRoutes, Target: &c.flagRoutes, Usage: "Filter output to only show routes.", }) f.BoolVar(&flag.BoolVar{ - Name: "endpoints", + Name: flagNameEndpoints, Target: &c.flagEndpoints, Usage: "Filter output to only show endpoints.", }) f.BoolVar(&flag.BoolVar{ - Name: "secrets", + Name: flagNameSecrets, Target: &c.flagSecrets, Usage: "Filter output to only show secrets.", }) f.StringVar(&flag.StringVar{ - Name: "fqdn", + Name: flagNameFQDN, Target: &c.flagFQDN, Usage: "Filter cluster output to clusters with a fully qualified domain name which contains the given value. May be combined with -address and -port.", }) f.StringVar(&flag.StringVar{ - Name: "address", + Name: flagNameAddress, Target: &c.flagAddress, Usage: "Filter clusters, endpoints, and listeners output to those with addresses which contain the given value. May be combined with -fqdn and -port", }) f.IntVar(&flag.IntVar{ - Name: "port", + Name: flagNamePort, Target: &c.flagPort, Usage: "Filter endpoints and listeners output to addresses with the given port number. May be combined with -fqdn and -address.", Default: -1, @@ -127,13 +141,13 @@ func (c *ReadCommand) init() { f = c.set.NewSet("GlobalOptions") f.StringVar(&flag.StringVar{ - Name: "kubeconfig", + Name: flagNameKubeConfig, Aliases: []string{"c"}, Target: &c.flagKubeConfig, Usage: "Set the path to kubeconfig file.", }) f.StringVar(&flag.StringVar{ - Name: "context", + Name: flagNameKubeContext, Target: &c.flagKubeContext, Usage: "Set the Kubernetes context to use.", }) @@ -193,6 +207,33 @@ func (c *ReadCommand) Synopsis() string { return "Inspect the Envoy configuration for a given Pod." } +// AutocompleteFlags returns a mapping of supported flags and autocomplete +// options for this command. The map key for the Flags map should be the +// complete flag such as "-foo" or "--foo". +func (c *ReadCommand) AutocompleteFlags() complete.Flags { + return complete.Flags{ + fmt.Sprintf("-%s", flagNameNamespace): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameOutput): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameClusters): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameListeners): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameRoutes): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameEndpoints): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameSecrets): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameFQDN): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameAddress): complete.PredictNothing, + fmt.Sprintf("-%s", flagNamePort): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameKubeConfig): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameKubeContext): complete.PredictNothing, + } +} + +// AutocompleteArgs returns the argument predictor for this command. +// Since argument completion is not supported, this will return +// complete.PredictNothing. +func (c *ReadCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + func (c *ReadCommand) parseFlags(args []string) error { // Separate positional arguments from keyed arguments. positional := []string{} diff --git a/cli/cmd/proxy/read/command_test.go b/cli/cmd/proxy/read/command_test.go index 9a6902ccae..27f19e7370 100644 --- a/cli/cmd/proxy/read/command_test.go +++ b/cli/cmd/proxy/read/command_test.go @@ -3,14 +3,18 @@ package read import ( "bytes" "context" + "flag" "fmt" "io" "os" "testing" "github.com/hashicorp/consul-k8s/cli/common" + cmnFlag "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/go-hclog" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -259,3 +263,35 @@ func setupCommand(buf io.Writer) *ReadCommand { return command } + +func TestTaskCreateCommand_AutocompleteFlags(t *testing.T) { + t.Parallel() + buf := new(bytes.Buffer) + cmd := setupCommand(buf) + + predictor := cmd.AutocompleteFlags() + + // Test that we get the expected number of predictions + args := complete.Args{Last: "-"} + res := predictor.Predict(args) + + // Grab the list of flags from the Flag object + flags := make([]string, 0) + cmd.set.VisitSets(func(name string, set *cmnFlag.Set) { + set.VisitAll(func(flag *flag.Flag) { + flags = append(flags, fmt.Sprintf("-%s", flag.Name)) + }) + }) + + // Verify that there is a prediction for each flag associated with the command + assert.Equal(t, len(flags), len(res)) + assert.ElementsMatch(t, flags, res, "flags and predictions didn't match, make sure to add "+ + "new flags to the command AutoCompleteFlags function") +} + +func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { + buf := new(bytes.Buffer) + cmd := setupCommand(buf) + c := cmd.AutocompleteArgs() + assert.Equal(t, complete.PredictNothing, c) +} diff --git a/cli/cmd/status/status.go b/cli/cmd/status/status.go index 926d8d790b..19f5a52398 100644 --- a/cli/cmd/status/status.go +++ b/cli/cmd/status/status.go @@ -6,6 +6,7 @@ import ( "strconv" "sync" + "github.com/posener/complete" "helm.sh/helm/v3/pkg/release" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -19,6 +20,11 @@ import ( "sigs.k8s.io/yaml" ) +const ( + flagNameKubeConfig = "kubeconfig" + flagNameKubeContext = "context" +) + type Command struct { *common.BaseCommand @@ -68,7 +74,7 @@ func (c *Command) Run(args []string) int { return 1 } - if err := c.validateFlags(args); err != nil { + if err := c.validateFlags(); err != nil { c.UI.Output(err.Error()) return 1 } @@ -124,13 +130,30 @@ func (c *Command) Run(args []string) int { } // validateFlags checks the command line flags and values for errors. -func (c *Command) validateFlags(args []string) error { +func (c *Command) validateFlags() error { if len(c.set.Args()) > 0 { return errors.New("should have no non-flag arguments") } return nil } +// AutocompleteFlags returns a mapping of supported flags and autocomplete +// options for this command. The map key for the Flags map should be the +// complete flag such as "-foo" or "--foo". +func (c *Command) AutocompleteFlags() complete.Flags { + return complete.Flags{ + fmt.Sprintf("-%s", flagNameKubeConfig): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameKubeContext): complete.PredictNothing, + } +} + +// AutocompleteArgs returns the argument predictor for this command. +// Since argument completion is not supported, this will return +// complete.PredictNothing. +func (c *Command) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + // checkHelmInstallation uses the helm Go SDK to depict the status of a named release. This function then prints // the version of the release, it's status (unknown, deployed, uninstalled, ...), and the overwritten values. func (c *Command) checkHelmInstallation(settings *helmCLI.EnvSettings, uiLogger action.DebugLog, releaseName, namespace string) error { diff --git a/cli/cmd/status/status_test.go b/cli/cmd/status/status_test.go index 79f908654f..b45ffef556 100644 --- a/cli/cmd/status/status_test.go +++ b/cli/cmd/status/status_test.go @@ -2,12 +2,16 @@ package status import ( "context" + "flag" "fmt" "os" "testing" "github.com/hashicorp/consul-k8s/cli/common" + cmnFlag "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/go-hclog" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" appsv1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -184,3 +188,33 @@ func getInitializedCommand(t *testing.T) *Command { c.init() return c } + +func TestTaskCreateCommand_AutocompleteFlags(t *testing.T) { + t.Parallel() + cmd := getInitializedCommand(t) + + predictor := cmd.AutocompleteFlags() + + // Test that we get the expected number of predictions + args := complete.Args{Last: "-"} + res := predictor.Predict(args) + + // Grab the list of flags from the Flag object + flags := make([]string, 0) + cmd.set.VisitSets(func(name string, set *cmnFlag.Set) { + set.VisitAll(func(flag *flag.Flag) { + flags = append(flags, fmt.Sprintf("-%s", flag.Name)) + }) + }) + + // Verify that there is a prediction for each flag associated with the command + assert.Equal(t, len(flags), len(res)) + assert.ElementsMatch(t, flags, res, "flags and predictions didn't match, make sure to add "+ + "new flags to the command AutoCompleteFlags function") +} + +func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { + cmd := getInitializedCommand(t) + c := cmd.AutocompleteArgs() + assert.Equal(t, complete.PredictNothing, c) +} diff --git a/cli/cmd/uninstall/uninstall.go b/cli/cmd/uninstall/uninstall.go index 01a442226d..07b945bf79 100644 --- a/cli/cmd/uninstall/uninstall.go +++ b/cli/cmd/uninstall/uninstall.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/consul-k8s/cli/helm" + "github.com/posener/complete" "helm.sh/helm/v3/pkg/action" helmCLI "helm.sh/helm/v3/pkg/cli" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -32,6 +33,9 @@ const ( flagTimeout = "timeout" defaultTimeout = "10m" + + flagContext = "context" + flagKubeconfig = "kubeconfig" ) type Command struct { @@ -91,14 +95,14 @@ func (c *Command) init() { f = c.set.NewSet("Global Options") f.StringVar(&flag.StringVar{ - Name: "kubeconfig", + Name: flagKubeconfig, Aliases: []string{"c"}, Target: &c.flagKubeConfig, Default: "", Usage: "Path to kubeconfig file.", }) f.StringVar(&flag.StringVar{ - Name: "context", + Name: flagContext, Target: &c.flagKubeContext, Default: "", Usage: "Kubernetes context to use.", @@ -277,7 +281,7 @@ func (c *Command) Run(args []string) int { return 1 } - if err := c.deleteSecrets(foundReleaseName, foundReleaseNamespace); err != nil { + if err := c.deleteSecrets(foundReleaseNamespace); err != nil { c.UI.Output(err.Error(), terminal.WithErrorStyle()) return 1 } @@ -325,6 +329,28 @@ func (c *Command) Synopsis() string { return "Uninstall Consul deployment." } +// AutocompleteFlags returns a mapping of supported flags and autocomplete +// options for this command. The map key for the Flags map should be the +// complete flag such as "-foo" or "--foo". +func (c *Command) AutocompleteFlags() complete.Flags { + return complete.Flags{ + fmt.Sprintf("-%s", flagAutoApprove): complete.PredictNothing, + fmt.Sprintf("-%s", flagNamespace): complete.PredictNothing, + fmt.Sprintf("-%s", flagReleaseName): complete.PredictNothing, + fmt.Sprintf("-%s", flagWipeData): complete.PredictNothing, + fmt.Sprintf("-%s", flagTimeout): complete.PredictNothing, + fmt.Sprintf("-%s", flagContext): complete.PredictNothing, + fmt.Sprintf("-%s", flagKubeconfig): complete.PredictFiles("*"), + } +} + +// AutocompleteArgs returns the argument predictor for this command. +// Since argument completion is not supported, this will return +// complete.PredictNothing. +func (c *Command) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + func (c *Command) findExistingInstallation(settings *helmCLI.EnvSettings, uiLogger action.DebugLog) (bool, string, string, error) { releaseName, namespace, err := common.CheckForInstallations(settings, uiLogger) if err != nil { @@ -378,7 +404,7 @@ func (c *Command) deletePVCs(foundReleaseName, foundReleaseNamespace string) err } // deleteSecrets deletes any secrets that have the label "managed-by" set to "consul-k8s". -func (c *Command) deleteSecrets(foundReleaseName, foundReleaseNamespace string) error { +func (c *Command) deleteSecrets(foundReleaseNamespace string) error { secrets, err := c.kubernetes.CoreV1().Secrets(foundReleaseNamespace).List(c.Ctx, metav1.ListOptions{ LabelSelector: common.CLILabelKey + "=" + common.CLILabelValue, }) diff --git a/cli/cmd/uninstall/uninstall_test.go b/cli/cmd/uninstall/uninstall_test.go index 7d36ce5d3d..8fa92e92b7 100644 --- a/cli/cmd/uninstall/uninstall_test.go +++ b/cli/cmd/uninstall/uninstall_test.go @@ -2,12 +2,17 @@ package uninstall import ( "context" + "flag" + "fmt" "os" "testing" "github.com/hashicorp/consul-k8s/cli/common" + cmnFlag "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/go-hclog" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" @@ -91,7 +96,7 @@ func TestDeleteSecrets(t *testing.T) { require.NoError(t, err) _, err = c.kubernetes.CoreV1().Secrets("default").Create(context.Background(), secret3, metav1.CreateOptions{}) require.NoError(t, err) - err = c.deleteSecrets("consul", "default") + err = c.deleteSecrets("default") require.NoError(t, err) secrets, err := c.kubernetes.CoreV1().Secrets("default").List(context.Background(), metav1.ListOptions{}) require.NoError(t, err) @@ -366,3 +371,33 @@ func getInitializedCommand(t *testing.T) *Command { c.init() return c } + +func TestTaskCreateCommand_AutocompleteFlags(t *testing.T) { + t.Parallel() + cmd := getInitializedCommand(t) + + predictor := cmd.AutocompleteFlags() + + // Test that we get the expected number of predictions + args := complete.Args{Last: "-"} + res := predictor.Predict(args) + + // Grab the list of flags from the Flag object + flags := make([]string, 0) + cmd.set.VisitSets(func(name string, set *cmnFlag.Set) { + set.VisitAll(func(flag *flag.Flag) { + flags = append(flags, fmt.Sprintf("-%s", flag.Name)) + }) + }) + + // Verify that there is a prediction for each flag associated with the command + assert.Equal(t, len(flags), len(res)) + assert.ElementsMatch(t, flags, res, "flags and predictions didn't match, make sure to add "+ + "new flags to the command AutoCompleteFlags function") +} + +func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { + cmd := getInitializedCommand(t) + c := cmd.AutocompleteArgs() + assert.Equal(t, complete.PredictNothing, c) +} diff --git a/cli/cmd/upgrade/upgrade.go b/cli/cmd/upgrade/upgrade.go index e145e238e1..e1bb744ce1 100644 --- a/cli/cmd/upgrade/upgrade.go +++ b/cli/cmd/upgrade/upgrade.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/consul-k8s/cli/common/terminal" "github.com/hashicorp/consul-k8s/cli/config" "github.com/hashicorp/consul-k8s/cli/helm" + "github.com/posener/complete" "helm.sh/helm/v3/pkg/action" helmCLI "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/cli/values" @@ -44,6 +45,9 @@ const ( flagNameWait = "wait" defaultWait = true + + flagNameContext = "context" + flagNameKubeconfig = "kubeconfig" ) type Command struct { @@ -143,14 +147,14 @@ func (c *Command) init() { f = c.set.NewSet("Global Options") f.StringVar(&flag.StringVar{ - Name: "kubeconfig", + Name: flagNameKubeconfig, Aliases: []string{"c"}, Target: &c.flagKubeConfig, Default: "", Usage: "Set the path to kubeconfig file.", }) f.StringVar(&flag.StringVar{ - Name: "context", + Name: flagNameContext, Target: &c.flagKubeContext, Default: "", Usage: "Set the Kubernetes context to use.", @@ -308,6 +312,33 @@ func (c *Command) Run(args []string) int { return 0 } +// AutocompleteFlags returns a mapping of supported flags and autocomplete +// options for this command. The map key for the Flags map should be the +// complete flag such as "-foo" or "--foo". +func (c *Command) AutocompleteFlags() complete.Flags { + return complete.Flags{ + fmt.Sprintf("-%s", flagNamePreset): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameConfigFile): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameSetStringValues): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameSetValues): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameFileValues): complete.PredictFiles("*"), + fmt.Sprintf("-%s", flagNameDryRun): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameAutoApprove): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameTimeout): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameVerbose): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameWait): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameContext): complete.PredictNothing, + fmt.Sprintf("-%s", flagNameKubeconfig): complete.PredictFiles("*"), + } +} + +// AutocompleteArgs returns the argument predictor for this command. +// Since argument completion is not supported, this will return +// complete.PredictNothing. +func (c *Command) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + // validateFlags checks that the user's provided flags are valid. func (c *Command) validateFlags(args []string) error { if err := c.set.Parse(args); err != nil { diff --git a/cli/cmd/upgrade/upgrade_test.go b/cli/cmd/upgrade/upgrade_test.go index f70496bda6..9b4636eb57 100644 --- a/cli/cmd/upgrade/upgrade_test.go +++ b/cli/cmd/upgrade/upgrade_test.go @@ -1,11 +1,16 @@ package upgrade import ( + "flag" + "fmt" "os" "testing" "github.com/hashicorp/consul-k8s/cli/common" + cmnFlag "github.com/hashicorp/consul-k8s/cli/common/flag" "github.com/hashicorp/go-hclog" + "github.com/posener/complete" + "github.com/stretchr/testify/assert" ) // TestValidateFlags tests the validate flags function. @@ -66,3 +71,33 @@ func getInitializedCommand(t *testing.T) *Command { c.init() return c } + +func TestTaskCreateCommand_AutocompleteFlags(t *testing.T) { + t.Parallel() + cmd := getInitializedCommand(t) + + predictor := cmd.AutocompleteFlags() + + // Test that we get the expected number of predictions + args := complete.Args{Last: "-"} + res := predictor.Predict(args) + + // Grab the list of flags from the Flag object + flags := make([]string, 0) + cmd.set.VisitSets(func(name string, set *cmnFlag.Set) { + set.VisitAll(func(flag *flag.Flag) { + flags = append(flags, fmt.Sprintf("-%s", flag.Name)) + }) + }) + + // Verify that there is a prediction for each flag associated with the command + assert.Equal(t, len(flags), len(res)) + assert.ElementsMatch(t, flags, res, "flags and predictions didn't match, make sure to add "+ + "new flags to the command AutoCompleteFlags function") +} + +func TestTaskCreateCommand_AutocompleteArgs(t *testing.T) { + cmd := getInitializedCommand(t) + c := cmd.AutocompleteArgs() + assert.Equal(t, complete.PredictNothing, c) +} diff --git a/cli/common/flag/set.go b/cli/common/flag/set.go index 6e5e615555..03ee353f80 100644 --- a/cli/common/flag/set.go +++ b/cli/common/flag/set.go @@ -43,23 +43,23 @@ func NewSets() *Sets { // NewSet creates a new single flag set. A set should be created for // any grouping of flags, for example "Common Options", "Auth Options", etc. -func (f *Sets) NewSet(name string) *Set { +func (s *Sets) NewSet(name string) *Set { flagSet := NewSet(name) // The union and completions are pointers to our own values - flagSet.unionSet = f.unionSet - flagSet.completions = f.completions + flagSet.unionSet = s.unionSet + flagSet.completions = s.completions // Keep track of it for help generation - f.flagSets = append(f.flagSets, flagSet) + s.flagSets = append(s.flagSets, flagSet) return flagSet } // GetSetFlags returns a slice of flags for a given set. // If the requested set does not exist, this will return an empty slice. -func (f *Sets) GetSetFlags(setName string) []string { +func (s *Sets) GetSetFlags(setName string) []string { var setFlags []string - for _, set := range f.flagSets { + for _, set := range s.flagSets { if set.name == setName { set.flagSet.VisitAll(func(f *flag.Flag) { setFlags = append(setFlags, fmt.Sprintf("-%s", f.Name)) @@ -72,36 +72,36 @@ func (f *Sets) GetSetFlags(setName string) []string { } // Completions returns the completions for this flag set. -func (f *Sets) Completions() complete.Flags { - return f.completions +func (s *Sets) Completions() complete.Flags { + return s.completions } // Parse parses the given flags, returning any errors. -func (f *Sets) Parse(args []string) error { - return f.unionSet.Parse(args) +func (s *Sets) Parse(args []string) error { + return s.unionSet.Parse(args) } // Parsed reports whether the command-line flags have been parsed. -func (f *Sets) Parsed() bool { - return f.unionSet.Parsed() +func (s *Sets) Parsed() bool { + return s.unionSet.Parsed() } // Args returns the remaining args after parsing. -func (f *Sets) Args() []string { - return f.unionSet.Args() +func (s *Sets) Args() []string { + return s.unionSet.Args() } // Visit visits the flags in lexicographical order, calling fn for each. It // visits only those flags that have been set. -func (f *Sets) Visit(fn func(*flag.Flag)) { - f.unionSet.Visit(fn) +func (s *Sets) Visit(fn func(*flag.Flag)) { + s.unionSet.Visit(fn) } // Help builds custom help for this command, grouping by flag set. -func (fs *Sets) Help() string { +func (s *Sets) Help() string { var out bytes.Buffer - for _, set := range fs.flagSets { + for _, set := range s.flagSets { printFlagTitle(&out, set.name+":") set.VisitAll(func(f *flag.Flag) { // Skip any hidden flags @@ -115,9 +115,10 @@ func (fs *Sets) Help() string { return strings.TrimRight(out.String(), "\n") } -// Help builds custom help for this command, grouping by flag set. -func (fs *Sets) VisitSets(fn func(name string, set *Set)) { - for _, set := range fs.flagSets { +// VisitSets visits each set and performs action based on the passed in +// function. +func (s *Sets) VisitSets(fn func(name string, set *Set)) { + for _, set := range s.flagSets { fn(set.name, set) } } diff --git a/cli/main.go b/cli/main.go index c979ec625a..0ffd03328c 100644 --- a/cli/main.go +++ b/cli/main.go @@ -15,6 +15,9 @@ func main() { c := cli.NewCLI("consul-k8s", version.GetHumanVersion()) c.Args = os.Args[1:] + // Enable CLI autocomplete + c.Autocomplete = true + log := hclog.New(&hclog.LoggerOptions{ Name: "cli", Level: hclog.Info, From 913f6e42fe4b06b220e1c5649cc6fd8a82c1fab0 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Mon, 19 Sep 2022 16:31:12 -0500 Subject: [PATCH 128/235] Re-enable MeshGW tests in acceptance on Kind and update CI binary versions (#1491) * Re-enables meshGW tests in Kind and updates Kind CI images to latest including latest Kube-1.24 versions. --- .circleci/config.yml | 12 ++++++------ acceptance/tests/mesh-gateway/main_test.go | 4 ---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 234ed85af5..f2264efd61 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -38,7 +38,7 @@ commands: sudo tar -C /usr/local/bin -xzf gotestsum_1.6.4_linux_amd64.tar.gz rm gotestsum_1.6.4_linux_amd64.tar.gz - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.14.0/kind-linux-amd64 + curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.15.0/kind-linux-amd64 chmod +x ./kind sudo mv ./kind /usr/local/bin/kind @@ -46,8 +46,8 @@ commands: chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl - wget https://get.helm.sh/helm-v3.7.0-linux-amd64.tar.gz - tar -zxvf helm-v3.7.0-linux-amd64.tar.gz + wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz + tar -zxvf helm-v3.9.4-linux-amd64.tar.gz sudo mv linux-amd64/helm /usr/local/bin/helm create-kind-clusters: parameters: @@ -506,7 +506,7 @@ jobs: - checkout - install-prereqs - create-kind-clusters: - version: "v1.24.0" + version: "v1.24.4" - restore_cache: keys: - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} @@ -538,7 +538,7 @@ jobs: - checkout - install-prereqs - create-kind-clusters: - version: "v1.24.0" + version: "v1.24.4" - restore_cache: keys: - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} @@ -570,7 +570,7 @@ jobs: - checkout - install-prereqs - create-kind-clusters: - version: "v1.24.0" + version: "v1.24.4" - restore_cache: keys: - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} diff --git a/acceptance/tests/mesh-gateway/main_test.go b/acceptance/tests/mesh-gateway/main_test.go index b7c6af4b90..fb8935441e 100644 --- a/acceptance/tests/mesh-gateway/main_test.go +++ b/acceptance/tests/mesh-gateway/main_test.go @@ -13,10 +13,6 @@ var suite testsuite.Suite func TestMain(m *testing.M) { suite = testsuite.NewSuite(m) - if suite.Config().UseKind { - fmt.Println("Skipping mesh gateway tests because they are currently flaky on kind") - os.Exit(0) - } if suite.Config().EnableMultiCluster { os.Exit(suite.Run()) } else { From a9eaaf4a7c51d11afd5821d6176e35f4d664d4ff Mon Sep 17 00:00:00 2001 From: John Murret Date: Tue, 20 Sep 2022 10:27:54 -0600 Subject: [PATCH 129/235] Update consul-helm-test image and CI to go 1.18 (#1498) * using the current circleci go image for 1.18 * updating consul-helm-test image to v0.12.0 --- .circleci/config.yml | 22 +++++++++++----------- .github/workflows/test.yml | 2 +- charts/consul/test/docker/Test.dockerfile | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f2264efd61..35d86cb13c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -485,7 +485,7 @@ jobs: unit-test-helm-templates: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout @@ -596,7 +596,7 @@ jobs: ########################## cleanup-gcp-resources: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - run: name: cleanup leftover resources @@ -614,7 +614,7 @@ jobs: cleanup-azure-resources: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - run: name: cleanup leftover resources @@ -632,7 +632,7 @@ jobs: cleanup-eks-resources: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout - run: @@ -659,7 +659,7 @@ jobs: - TEST_RESULTS: /tmp/test-results docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - run: @@ -727,7 +727,7 @@ jobs: - TEST_RESULTS: /tmp/test-results docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - run: @@ -795,7 +795,7 @@ jobs: - TEST_RESULTS: /tmp/test-results docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout @@ -852,7 +852,7 @@ jobs: - TEST_RESULTS: /tmp/test-results docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout @@ -908,7 +908,7 @@ jobs: - TEST_RESULTS: /tmp/test-results docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout @@ -971,7 +971,7 @@ jobs: - TEST_RESULTS: /tmp/test-results docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout @@ -1034,7 +1034,7 @@ jobs: parallelism: 1 docker: # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 steps: - checkout diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4d651e8769..ce1033a540 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,7 +74,7 @@ jobs: - unit-helm-gen runs-on: ubuntu-latest container: - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.11.0 + image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 options: --user 1001 steps: - name: Checkout code diff --git a/charts/consul/test/docker/Test.dockerfile b/charts/consul/test/docker/Test.dockerfile index fdf51b162e..2fccf196d3 100644 --- a/charts/consul/test/docker/Test.dockerfile +++ b/charts/consul/test/docker/Test.dockerfile @@ -6,7 +6,7 @@ # a script to configure kubectl, potentially install Helm, and run the tests # manually. This image only has the dependencies pre-installed. -FROM circleci/golang:1.18 +FROM cimg/go:1.18 # change the user to root so we can install stuff USER root From 113a266b687881e55676bd8cfa77f3275685368d Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Tue, 20 Sep 2022 15:25:20 -0700 Subject: [PATCH 130/235] add `release/**` wild card to ci.hcl (#1518) * add `release/**` wild card - branches with a leading `release/` will be categorized as release branches * change CRT messaging to be sent to feed-consul-k8s-ci --- .release/ci.hcl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.release/ci.hcl b/.release/ci.hcl index 1506406aa4..cf905516f1 100644 --- a/.release/ci.hcl +++ b/.release/ci.hcl @@ -3,12 +3,15 @@ schema = "1" project "consul-k8s" { team = "consul-k8s" slack { - notification_channel = "CBXF3CGAF" # team-consul-kubernetes + notification_channel = "C0421KHNAV9" # feed-consul-k8s-ci } github { organization = "hashicorp" repository = "consul-k8s" - release_branches = ["main"] + release_branches = [ + "main", + "release/**", + ] } } From 5f0eb3ecf1080fb3fa04806faca07eae242b371f Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Fri, 23 Sep 2022 08:12:04 -0500 Subject: [PATCH 131/235] update docs for helm for global.syncCatalog.aclSyncToken (#1524) * update docs for helm for global.syncCatalog.aclSyncToken * Update charts/consul/values.yaml Co-authored-by: Luke Kysow <1034429+lkysow@users.noreply.github.com> Co-authored-by: Luke Kysow <1034429+lkysow@users.noreply.github.com> --- charts/consul/values.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 70ed773cf2..cfe87e1205 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -1795,12 +1795,12 @@ syncCatalog: # Refers to a Kubernetes secret that you have created that contains # an ACL token for your Consul cluster which allows the sync process the correct - # permissions. This is only needed if ACLs are enabled on the Consul cluster. + # permissions. This is only needed if ACLs are managed manually within the Consul cluster, i.e. `global.acls.manageSystemACLs` is `false`. aclSyncToken: - # The name of the Vault secret that holds the acl sync token. + # The name of the Kubernetes secret that holds the acl sync token. # @type: string secretName: null - # The key within the Vault secret that holds the acl sync. + # The key within the Kubernetes secret that holds the acl sync token. # @type: string secretKey: null From 2b2a8edea8e8fefd385deb4b2e424e9770862c6d Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Fri, 23 Sep 2022 10:20:16 -0400 Subject: [PATCH 132/235] Populate primary dc flag for APIGW controller in secondary federated dc (#1511) * Populate primary dc flag for APIGW controller in secondary federated dc * Add test coverage for primary-datacenter flag * Add changelog entry * Update CHANGELOG.md Co-authored-by: Kyle Schochenmaier Co-authored-by: Kyle Schochenmaier --- CHANGELOG.md | 4 +++ .../api-gateway-controller-deployment.yaml | 3 +++ .../api-gateway-controller-deployment.bats | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 39fdbdbf5c..e75cf6fc62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ BUG FIXES: * Control plane * Use global ACL auth method to provision ACL tokens for API Gateway in secondary datacenter [[GH-1481](https://github.com/hashicorp/consul-k8s/pull/1481)] +IMPROVEMENTS: +* Helm: + * API Gateway: Set primary datacenter flag when deploying controller into secondary datacenter with federation enabled [[GH-1511](https://github.com/hashicorp/consul-k8s/pull/1511)] + ## 0.48.0 (September 01, 2022) FEATURES: diff --git a/charts/consul/templates/api-gateway-controller-deployment.yaml b/charts/consul/templates/api-gateway-controller-deployment.yaml index b090cbcb7f..22d14c1e48 100644 --- a/charts/consul/templates/api-gateway-controller-deployment.yaml +++ b/charts/consul/templates/api-gateway-controller-deployment.yaml @@ -90,6 +90,9 @@ spec: {{- end }} {{- end }} {{- end }} + {{- if and .Values.global.federation.enabled .Values.global.federation.primaryDatacenter }} + -primary-datacenter={{ .Values.global.federation.primaryDatacenter }} \ + {{- end }} -log-level {{ default .Values.global.logLevel .Values.apiGateway.logLevel }} \ -log-json={{ .Values.global.logJSON }} volumeMounts: diff --git a/charts/consul/test/unit/api-gateway-controller-deployment.bats b/charts/consul/test/unit/api-gateway-controller-deployment.bats index 51273c1b77..60adc84076 100755 --- a/charts/consul/test/unit/api-gateway-controller-deployment.bats +++ b/charts/consul/test/unit/api-gateway-controller-deployment.bats @@ -400,6 +400,32 @@ load _helpers [ "${actual}" = "true" ] } +@test "apiGateway/Deployment: primary-datacenter flag provided when federation enabled in non-primary datacenter" { + cd `chart_dir` + local object=$(helm template \ + -s templates/api-gateway-controller-deployment.yaml \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=foo' \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.tls.enableAutoEncrypt=true' \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.datacenter=dc2' \ + --set 'global.federation.enabled=true' \ + --set 'global.federation.primaryDatacenter=dc1' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[] | select(.name == "api-gateway-controller")' | tee /dev/stderr) + + local actual=$(echo $object | + yq -r '.command | any(contains("consul-api-gateway server"))' | tee /dev/stderr) + [ "${actual}" = "true" ] + + local actual=$(echo $object | + yq -r '.command | any(contains("-primary-datacenter=dc1"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + @test "apiGateway/Deployment: init container is created when global.acls.manageSystemACLs=true and has correct command when federation enabled in non-primary datacenter" { cd `chart_dir` local object=$(helm template \ From ffcd208201e171b6daf9a60e261754632424b6f9 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Mon, 26 Sep 2022 09:56:26 -0500 Subject: [PATCH 133/235] fix a typo in the helper template for pdb (#1530) * fix a typo in the helper template for pdb --- CHANGELOG.md | 2 ++ charts/consul/templates/_helpers.tpl | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e75cf6fc62..6bb0faae72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ FEATURES: BUG FIXES: * Control plane * Use global ACL auth method to provision ACL tokens for API Gateway in secondary datacenter [[GH-1481](https://github.com/hashicorp/consul-k8s/pull/1481)] +* Helm: + * Fixes a typo in the templating of `global.connectInject.disruptionBudget.maxUnavailable`. [[GH-1530](https://github.com/hashicorp/consul-k8s/pull/1530)]. IMPROVEMENTS: * Helm: diff --git a/charts/consul/templates/_helpers.tpl b/charts/consul/templates/_helpers.tpl index fceb75ce5a..02b2adb39e 100644 --- a/charts/consul/templates/_helpers.tpl +++ b/charts/consul/templates/_helpers.tpl @@ -200,7 +200,7 @@ Add a special case for replicas=1, where it should default to 0 as well. {{- if eq (int .Values.connectInject.replicas) 1 -}} {{ 0 }} {{- else if .Values.connectInject.disruptionBudget.maxUnavailable -}} -{{ .Values.server.disruptionBudget.maxUnavailable -}} +{{ .Values.connectInject.disruptionBudget.maxUnavailable -}} {{- else -}} {{- if eq (int .Values.connectInject.replicas) 3 -}} {{- 1 -}} From b89e65427fc44812a4fda74d137d5a7741106e74 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Mon, 26 Sep 2022 10:19:57 -0500 Subject: [PATCH 134/235] downgrade helm version again (#1525) --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 35d86cb13c..3196ac2e50 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -46,8 +46,8 @@ commands: chmod +x ./kubectl sudo mv ./kubectl /usr/local/bin/kubectl - wget https://get.helm.sh/helm-v3.9.4-linux-amd64.tar.gz - tar -zxvf helm-v3.9.4-linux-amd64.tar.gz + wget https://get.helm.sh/helm-v3.7.0-linux-amd64.tar.gz + tar -zxvf helm-v3.7.0-linux-amd64.tar.gz sudo mv linux-amd64/helm /usr/local/bin/helm create-kind-clusters: parameters: From 861bfb574ba021459ce7bc6e175c6806d1efbe0b Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Fri, 16 Sep 2022 14:53:23 +0000 Subject: [PATCH 135/235] backport of commit 8a97da41a4ae9adadeb3e725e926ce5db2d6fe17 --- charts/consul/templates/cni-clusterrole.yaml | 8 ++ charts/consul/templates/cni-daemonset.yaml | 1 + .../cni-networkattachmentdefinition.yaml | 25 ++++ .../cni-securitycontextconstraints.yaml | 50 ++++++++ charts/consul/test/unit/cni-daemonset.bats | 5 + .../unit/cni-networkattachmentdefinition.bats | 61 ++++++++++ .../unit/cni-securitycontextcontstraints.bats | 33 ++++++ charts/consul/values.yaml | 15 ++- control-plane/cni/main.go | 49 ++++---- .../subcommand/install-cni/cniconfig.go | 48 +++++++- .../subcommand/install-cni/cniconfig_test.go | 57 +++++++-- .../subcommand/install-cni/command.go | 109 +++++++++++------- .../testdata/00-chained-plugins.conflist | 23 ++++ .../00-chained-plugins.conflist.golden | 32 +++++ .../testdata/00-single-plugin.conf | 18 +++ 15 files changed, 463 insertions(+), 71 deletions(-) create mode 100644 charts/consul/templates/cni-networkattachmentdefinition.yaml create mode 100644 charts/consul/templates/cni-securitycontextconstraints.yaml create mode 100644 charts/consul/test/unit/cni-networkattachmentdefinition.bats create mode 100644 charts/consul/test/unit/cni-securitycontextcontstraints.bats create mode 100644 control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist create mode 100644 control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist.golden create mode 100644 control-plane/subcommand/install-cni/testdata/00-single-plugin.conf diff --git a/charts/consul/templates/cni-clusterrole.yaml b/charts/consul/templates/cni-clusterrole.yaml index 84551205c0..39dc5ead50 100644 --- a/charts/consul/templates/cni-clusterrole.yaml +++ b/charts/consul/templates/cni-clusterrole.yaml @@ -27,4 +27,12 @@ rules: - {{ template "consul.fullname" . }}-cni verbs: - use +{{- if .Values.global.openshift.enabled}} +- apiGroups: ["security.openshift.io"] + resources: ["securitycontextconstraints"] + resourceNames: + - {{ template "consul.fullname" . }}-cni + verbs: + - use +{{- end }} {{- end }} diff --git a/charts/consul/templates/cni-daemonset.yaml b/charts/consul/templates/cni-daemonset.yaml index a74693da57..7b9f90d939 100644 --- a/charts/consul/templates/cni-daemonset.yaml +++ b/charts/consul/templates/cni-daemonset.yaml @@ -63,6 +63,7 @@ spec: - -log-level={{ default .Values.global.logLevel .Values.connectInject.cni.logLevel }} - -cni-bin-dir={{ .Values.connectInject.cni.cniBinDir }} - -cni-net-dir={{ .Values.connectInject.cni.cniNetDir }} + - -multus={{ .Values.connectInject.cni.multus }} {{- with .Values.connectInject.cni.resources }} resources: {{- toYaml . | nindent 12 }} diff --git a/charts/consul/templates/cni-networkattachmentdefinition.yaml b/charts/consul/templates/cni-networkattachmentdefinition.yaml new file mode 100644 index 0000000000..d0feaf5cb1 --- /dev/null +++ b/charts/consul/templates/cni-networkattachmentdefinition.yaml @@ -0,0 +1,25 @@ +{{- if (and (.Values.connectInject.cni.enabled) (.Values.connectInject.cni.multus)) }} +apiVersion: "k8s.cni.cncf.io/v1" +kind: NetworkAttachmentDefinition +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni +spec: + config: '{ + "cniVersion": "0.3.1", + "type": "consul-cni", + "cni_bin_dir": "{{ .Values.connectInject.cni.cniBinDir }}", + "cni_net_dir": "{{ .Values.connectInject.cni.cniNetDir }}", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "{{ default .Values.global.logLevel .Values.connectInject.cni.logLevel }}", + "multus": true, + "name": "consul-cni", + "type": "consul-cni" + }' +{{- end }} diff --git a/charts/consul/templates/cni-securitycontextconstraints.yaml b/charts/consul/templates/cni-securitycontextconstraints.yaml new file mode 100644 index 0000000000..6e76aefd84 --- /dev/null +++ b/charts/consul/templates/cni-securitycontextconstraints.yaml @@ -0,0 +1,50 @@ +{{- if (and (.Values.connectInject.cni.enabled) (.Values.global.openshift.enabled)) }} +apiVersion: security.openshift.io/v1 +kind: SecurityContextConstraints +metadata: + name: {{ template "consul.fullname" . }}-cni + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: cni + annotations: + kubernetes.io/description: {{ template "consul.fullname" . }}-cni are the security context constraints required + to run consul-cni. +allowHostDirVolumePlugin: true +allowHostIPC: false +allowHostNetwork: true +allowHostPID: false +allowHostPorts: true +allowPrivilegeEscalation: true +allowPrivilegedContainer: true +allowedCapabilities: null +defaultAddCapabilities: null +fsGroup: + type: MustRunAs +groups: [] +priority: null +readOnlyRootFilesystem: false +requiredDropCapabilities: +- KILL +- MKNOD +- SETUID +- SETGID +runAsUser: + type: MustRunAsRange +seLinuxContext: + type: MustRunAs +supplementalGroups: + type: MustRunAs +users: [] +volumes: +- configMap +- downwardAPI +- emptyDir +- persistentVolumeClaim +- projected +- secret +- hostPath +{{- end }} diff --git a/charts/consul/test/unit/cni-daemonset.bats b/charts/consul/test/unit/cni-daemonset.bats index e826642a00..0c423abfec 100644 --- a/charts/consul/test/unit/cni-daemonset.bats +++ b/charts/consul/test/unit/cni-daemonset.bats @@ -63,6 +63,7 @@ load _helpers --set 'connectInject.cni.logLevel=bar' \ --set 'connectInject.cni.cniBinDir=baz' \ --set 'connectInject.cni.cniNetDir=foo' \ + --set 'connectInject.cni.multus=false' \ bar \ . | tee /dev/stderr | yq '.spec.template.spec.containers[0].command' | tee /dev/stderr) @@ -86,6 +87,10 @@ load _helpers local actual=$(echo "$cmd" | yq 'any(contains("cni-net-dir=foo"))' | tee /dev/stderr) [ "${actual}" = "true" ] + + local actual=$(echo "$cmd" | + yq 'any(contains("multus=false"))' | tee /dev/stderr) + [ "${actual}" = "true" ] } #-------------------------------------------------------------------- diff --git a/charts/consul/test/unit/cni-networkattachmentdefinition.bats b/charts/consul/test/unit/cni-networkattachmentdefinition.bats new file mode 100644 index 0000000000..a7f0d1da03 --- /dev/null +++ b/charts/consul/test/unit/cni-networkattachmentdefinition.bats @@ -0,0 +1,61 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/NetworkAttachmentDefinition: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-networkattachmentdefinition.yaml \ + . +} + +@test "cni/NetworkAttachmentDefinition: disabled when cni enabled and multus disabled" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-securitycontextconstraints.yaml \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.cni.multus=false' \ + . +} + +@test "cni/NetworkAttachmentDefinition: enabled when cni enabled and multus enabled" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-networkattachmentdefinition.yaml \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.cni.multus=true' \ + . | tee /dev/stderr | + yq -s 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "cni/NetworkAttachmentDefinition: config is set" { + cd `chart_dir` + local cmd=$(helm template \ + -s templates/cni-networkattachmentdefinition.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.multus=true' \ + --set 'connectInject.cni.logLevel=bar' \ + --set 'connectInject.cni.cniBinDir=baz' \ + --set 'connectInject.cni.cniNetDir=foo' \ + bar \ + . | tee /dev/stderr | + yq -rc '.spec.config' | tee /dev/stderr) + + local actual=$(echo "$cmd" | + yq '.log_level' | tee /dev/stderr) + [ "${actual}" = '"bar"' ] + + local actual=$(echo "$cmd" | + yq '.cni_bin_dir' | tee /dev/stderr) + [ "${actual}" = '"baz"' ] + + local actual=$(echo "$cmd" | + yq '.cni_net_dir' | tee /dev/stderr) + [ "${actual}" = '"foo"' ] + +} + diff --git a/charts/consul/test/unit/cni-securitycontextcontstraints.bats b/charts/consul/test/unit/cni-securitycontextcontstraints.bats new file mode 100644 index 0000000000..759979aee2 --- /dev/null +++ b/charts/consul/test/unit/cni-securitycontextcontstraints.bats @@ -0,0 +1,33 @@ +#!/usr/bin/env bats + +load _helpers + +@test "cni/SecurityContextConstraints: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-securitycontextconstraints.yaml \ + . +} + +@test "cni/SecurityContextConstraints: disabled when cni disabled and global.openshift.enabled=true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/cni-securitycontextconstraints.yaml \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.enabled=false' \ + --set 'global.openshift.enabled=true' \ + . +} + +@test "cni/SecurityContextConstraints: enabled when cni enabled and global.openshift.enabled=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-securitycontextconstraints.yaml \ + --set 'connectInject.enabled=true' \ + --set 'connectInject.cni.enabled=true' \ + --set 'global.openshift.enabled=true' \ + . | tee /dev/stderr | + yq -s 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 72b447814c..1489faac75 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -1960,7 +1960,20 @@ connectInject: # Location on the kubernetes node of all CNI configuration. Should be the absolute path and start with a '/' # @type: string cniNetDir: "/etc/cni/net.d" - + + # If multus CNI plugin is enabled with consul-cni. When enabled, consul-cni will not be installed as a chained + # CNI plugin. Instead, a NetworkAttachementDefinition CustomResourceDefinition (CRD) will be created in the helm + # release namespace. Following multus plugin standards, an annotation is required in order for the consul-cni plugin + # to be executed and for your service to be added to the Consul Service Mesh. + # + # Add the annotation `'k8s.v1.cni.cncf.io/networks': '[{ "name":"consul-cni","namespace": "consul" }]'` to your pod + # to use the default installed NetworkAttachementDefinition CRD. + # + # Please refer to the [Multus Quickstart Guide](https://github.com/k8snetworkplumbingwg/multus-cni/blob/master/docs/quickstart.md) + # for more information about using multus. + # @type: string + multus: false + # The resource settings for CNI installer daemonset. # @recurse: false # @type: map diff --git a/control-plane/cni/main.go b/control-plane/cni/main.go index c0685efb52..24c473a853 100644 --- a/control-plane/cni/main.go +++ b/control-plane/cni/main.go @@ -137,26 +137,28 @@ func (c *Command) cmdAdd(args *skel.CmdArgs) error { Level: hclog.LevelFromString(cfg.LogLevel), }) - // Check to see if the plugin is a chained plugin. - if cfg.PrevResult == nil { - return fmt.Errorf("must be called as final chained plugin") - } - logger.Debug("consul-cni plugin config", "config", cfg) - // Convert the PrevResult to a concrete Result type that can be modified. The CNI standard says - // that the previous result needs to be passed onto the next plugin. - prevResult, err := current.GetResult(cfg.PrevResult) - if err != nil { - return fmt.Errorf("failed to convert prevResult: %w", err) - } - if len(prevResult.IPs) == 0 { - return fmt.Errorf("got no container IPs") - } + // Only chained plugins have a previous result. + var result *current.Result - // Pass the prevResult through this plugin to the next one. - result := prevResult - logger.Debug("consul-cni previous result", "result", result) + // Check to see if the plugin is a chained plugin. + if cfg.PrevResult == nil { + // The plugin is not chained (ie multus) so create a fake result + result = ¤t.Result{ + CNIVersion: "0.3.1", + } + } else { + prevResult, err := current.GetResult(cfg.PrevResult) + if err != nil { + return fmt.Errorf("failed to convert prevResult: %w", err) + } + if len(prevResult.IPs) == 0 { + return fmt.Errorf("got no container IPs") + } + // Pass the prevResult through this plugin to the next one. + result = prevResult + } ctx := context.Background() if c.client == nil { @@ -186,7 +188,7 @@ func (c *Command) cmdAdd(args *skel.CmdArgs) error { // We do not throw an error here because kubernetes will often throw a benign error where the pod has been // updated in between the get and update of the annotation. Eventually kubernetes will update the annotation - ok := c.updateTransparentProxyStatusAnnotation(pod, podNamespace, waiting) + ok := c.updateTransparentProxyStatusAnnotation(podName, podNamespace, waiting) if !ok { logger.Info("unable to update %s pod annotation to waiting", keyTransparentProxyStatus) } @@ -213,7 +215,7 @@ func (c *Command) cmdAdd(args *skel.CmdArgs) error { // We do not throw an error here because kubernetes will often throw a benign error where the pod has been // updated in between the get and update of the annotation. Eventually kubernetes will update the annotation - ok = c.updateTransparentProxyStatusAnnotation(pod, podNamespace, complete) + ok = c.updateTransparentProxyStatusAnnotation(podName, podNamespace, complete) if !ok { logger.Info("unable to update %s pod annotation to complete", keyTransparentProxyStatus) } @@ -270,8 +272,13 @@ func parseAnnotation(pod corev1.Pod, annotation string) (iptables.Config, error) // updateTransparentProxyStatusAnnotation updates the transparent-proxy-status annotation. We use it as a simple inicator of // CNI status on the pod. Failing is not fatal. -func (c *Command) updateTransparentProxyStatusAnnotation(pod *corev1.Pod, namespace, status string) bool { +func (c *Command) updateTransparentProxyStatusAnnotation(podName, namespace, status string) bool { + // Refresh the pod so that we can update it without problems + pod, err := c.client.CoreV1().Pods(namespace).Get(context.Background(), podName, metav1.GetOptions{}) + if err != nil { + return false + } pod.Annotations[keyTransparentProxyStatus] = status - _, err := c.client.CoreV1().Pods(namespace).Update(context.Background(), pod, metav1.UpdateOptions{}) + _, err = c.client.CoreV1().Pods(namespace).Update(context.Background(), pod, metav1.UpdateOptions{}) return err == nil } diff --git a/control-plane/subcommand/install-cni/cniconfig.go b/control-plane/subcommand/install-cni/cniconfig.go index 2c40bcda36..e4d2078ad7 100644 --- a/control-plane/subcommand/install-cni/cniconfig.go +++ b/control-plane/subcommand/install-cni/cniconfig.go @@ -16,7 +16,7 @@ import ( // defaultCNIConfigFile gets the the correct config file from the cni net dir. // Adapted from kubelet: https://github.com/kubernetes/kubernetes/blob/954996e231074dc7429f7be1256a579bedd8344c/pkg/kubelet/dockershim/network/cni/cni.go#L134. func defaultCNIConfigFile(dir string) (string, error) { - files, err := libcni.ConfFiles(dir, []string{".conf", ".conflist", ".json"}) + files, err := libcni.ConfFiles(dir, []string{".conf", ".conflist"}) if err != nil { return "", fmt.Errorf("error while trying to find files in %s: %w", dir, err) } @@ -58,13 +58,57 @@ func defaultCNIConfigFile(dir string) (string, error) { // CNI config list has no networks, skipping". continue } - return confFile, nil } // There were files but none of them were valid return "", fmt.Errorf("no valid config files found in %s", dir) } +// confListFileFromConfFile converts a .conf file into a .conflist file. Chained plugins use .conflist files. +func confListFileFromConfFile(cfgFile string) (string, error) { + if !strings.HasSuffix(cfgFile, ".conf") { + return "", fmt.Errorf("invalid conf file: %s", cfgFile) + } + + // Convert the .conf file into a map so that we can remove pieces of it. + cfgMap, err := configFileToMap(cfgFile) + if err != nil { + return "", fmt.Errorf("could not convert .conf file to map: %w", err) + } + + // Remove the cniVersion header from the conf map. + delete(cfgMap, "cniVersion") + + // Create the new plugins: [] section and add the contents from cfgMap to it. + plugins := make([]map[string]interface{}, 1) + plugins[0] = cfgMap + + listMap := map[string]interface{}{ + "name": "k8s-pod-network", + "cniVersion": "0.3.1", + "plugins": plugins, + } + + listFile := fmt.Sprintf("%s%s", cfgFile, "list") + + // Marshal into a new json object. + listJSON, err := json.MarshalIndent(listMap, "", " ") + if err != nil { + return "", fmt.Errorf("error marshalling conflist: %w", err) + } + + // Libcni nuance/bug. If the newline is missing, the cni plugin will throw errors saying that it cannot get parse the config. + listJSON = append(listJSON, "\n"...) + + // Write the .conflist file out. + err = os.WriteFile(listFile, listJSON, os.FileMode(0o644)) + if err != nil { + return "", fmt.Errorf("error writing conflist file %s: %w", listFile, err) + } + + return listFile, nil +} + // The format of the main cni config file is unstructured json consisting of a header and list of plugins // // { diff --git a/control-plane/subcommand/install-cni/cniconfig_test.go b/control-plane/subcommand/install-cni/cniconfig_test.go index 961d59cba6..640b9d93cb 100644 --- a/control-plane/subcommand/install-cni/cniconfig_test.go +++ b/control-plane/subcommand/install-cni/cniconfig_test.go @@ -26,10 +26,11 @@ func TestDefaultCNIConfigFile_NoFiles(t *testing.T) { // TestDefaultCNIConfigFile tests finding the correct config file in the cniNetDir directory. func TestDefaultCNIConfigFile(t *testing.T) { cases := []struct { - name string - cfgFile string - dir func(string) string - expectedErr error + name string + cfgFile string + dir func(string) string + expectedFile string + expectedErr error }{ { name: "valid .conflist file found", @@ -42,7 +43,8 @@ func TestDefaultCNIConfigFile(t *testing.T) { } return tempDir }, - expectedErr: nil, + expectedFile: "10-kindnet.conflist", + expectedErr: nil, }, { name: "several files, should choose .conflist file", @@ -60,7 +62,8 @@ func TestDefaultCNIConfigFile(t *testing.T) { return tempDir }, - expectedErr: nil, + expectedFile: "10-kindnet.conflist", + expectedErr: nil, }, } for _, c := range cases { @@ -68,14 +71,38 @@ func TestDefaultCNIConfigFile(t *testing.T) { tempDir := c.dir(c.cfgFile) actual, err := defaultCNIConfigFile(tempDir) - filename := filepath.Base(c.cfgFile) - filepath := filepath.Join(tempDir, filename) + filepath := filepath.Join(tempDir, c.expectedFile) require.Equal(t, filepath, actual) require.Equal(t, c.expectedErr, err) }) } } +func TestConfListFromConfFile(t *testing.T) { + + cfgFile := "testdata/00-single-plugin.conf" + expectedCfgFile := "testdata/00-chained-plugins.conflist" + + tempDir := t.TempDir() + err := copyFile(cfgFile, tempDir) + require.NoError(t, err) + + filename := filepath.Base(cfgFile) + tempCfgFile := filepath.Join(tempDir, filename) + + actualFile, err := confListFileFromConfFile(tempCfgFile) + require.NoError(t, err) + + actual, err := ioutil.ReadFile(actualFile) + require.NoError(t, err) + + expected, err := ioutil.ReadFile(expectedCfgFile) + require.NoError(t, err) + + require.Equal(t, string(expected), string(actual)) + +} + // TestCreateCNIConfigFile tests the writing of the config file. func TestAppendCNIConfig(t *testing.T) { cases := []struct { @@ -112,6 +139,20 @@ func TestAppendCNIConfig(t *testing.T) { cfgFile: "testdata/10-calico.conflist", goldenFile: "testdata/10-calico.conflist.golden", }, + { + name: "chained plugin file", + consulConfig: &config.CNIConfig{ + Name: config.DefaultPluginName, + Type: config.DefaultPluginType, + CNIBinDir: "/var/lib/cni/bin", + CNINetDir: "/etc/kubernetes/cni/net.d", + Kubeconfig: config.DefaultKubeconfig, + LogLevel: config.DefaultLogLevel, + Multus: config.DefaultMultus, + }, + cfgFile: "testdata/00-chained-plugins.conflist", + goldenFile: "testdata/00-chained-plugins.conflist.golden", + }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { diff --git a/control-plane/subcommand/install-cni/command.go b/control-plane/subcommand/install-cni/command.go index 22c1acdf84..7c481a0800 100644 --- a/control-plane/subcommand/install-cni/command.go +++ b/control-plane/subcommand/install-cni/command.go @@ -7,6 +7,7 @@ import ( "os" "os/signal" "path/filepath" + "strings" "sync" "syscall" @@ -117,7 +118,7 @@ func (c *Command) Run(args []string) int { defer cancel() // Generate the kubeconfig file that will be used by the plugin to communicate with the kubernetes api. - c.logger.Debug("Creating kubeconfig", "file", cfg.Kubeconfig) + c.logger.Info("Creating kubeconfig", "file", cfg.Kubeconfig) err := createKubeConfig(cfg.CNINetDir, cfg.Kubeconfig) if err != nil { c.logger.Error("could not create kube config", "error", err) @@ -125,7 +126,7 @@ func (c *Command) Run(args []string) int { } // Copy the consul-cni binary from the installer container to the host. - c.logger.Debug("Copying consul-cni binary", "destination", cfg.CNIBinDir) + c.logger.Info("Copying consul-cni binary", "destination", cfg.CNIBinDir) srcFile := filepath.Join(c.flagCNIBinSourceDir, consulCNIName) err = copyFile(srcFile, cfg.CNIBinDir) if err != nil { @@ -134,32 +135,50 @@ func (c *Command) Run(args []string) int { } // Get the config file that is on the host. - c.logger.Debug("Getting default config file from", "destination", cfg.CNINetDir) + c.logger.Info("Getting default config file from", "destination", cfg.CNINetDir) cfgFile, err := defaultCNIConfigFile(cfg.CNINetDir) if err != nil { c.logger.Error("could not get default CNI config file", "error", err) return 1 } - // The config file does not exist and it probably means that the consul-cni plugin was installed or scheduled - // before other cni plugins on the node. We will add a directory watcher and wait for another plugin to - // be installed. - if cfgFile == "" { - c.logger.Info("CNI config file not found. Consul-cni is a chained plugin and another plugin must be installed first. Waiting...", "directory", cfg.CNINetDir) - } else { - // Check if there is valid config in the config file. It is invalid if no consul-cni config exists, - // the consul-cni config is not the last in the plugin chain or the consul-cni config is different from - // what is passed into helm (it could happen in a helm upgrade). - err := validConfig(cfg, cfgFile) - if err != nil { - // The invalid config is not critical and we can recover from it. - c.logger.Info("Installing plugin", "reason", err) - err = appendCNIConfig(cfg, cfgFile) + // Install as a chained plugin. + if !cfg.Multus { + if strings.HasSuffix(cfgFile, ".conf") { + c.logger.Info("Converting .conf file to .conflist file", "file", cfgFile) + cfgFile, err = confListFileFromConfFile(cfgFile) if err != nil { - c.logger.Error("could not append configuration to config file", "error", err) + c.logger.Error("could convert .conf file to .conflist file", "error", err) return 1 } } + + // The config file does not exist and it probably means that the consul-cni plugin was installed or scheduled + // before other cni plugins on the node. We will add a directory watcher and wait for another plugin to + // be installed. + if cfgFile == "" { + c.logger.Info("CNI config file not found. Consul-cni is a chained plugin and another plugin must be installed first. Waiting...", "directory", cfg.CNINetDir) + } else { + // Check if there is valid config in the config file. It is invalid if no consul-cni config exists, + // the consul-cni config is not the last in the plugin chain or the consul-cni config is different from + // what is passed into helm (it could happen in a helm upgrade). + c.logger.Info("Using config file", "file", cfgFile) + err := validConfig(cfg, cfgFile) + if err != nil { + // The invalid config is not critical and we can recover from it. + c.logger.Info("Installing plugin", "reason", err) + err = appendCNIConfig(cfg, cfgFile) + if err != nil { + c.logger.Error("could not append configuration to config file", "error", err) + return 1 + } + } + } + } else { + // When multus is enabled, the plugin configuration is set in a NetworkAttachementDefinition CRD and multus + // handles the configuration and running of the consul-cni plugin. Also, we add a `k8s.v1.cni.cncf.io/networks: consul-cni` + // annotation during connect inject so that multus knows to run the consul-cni plugin. + c.logger.Info("Multus enabled, using multus NetworkAttachementDefinition for configuration") } // Watch for changes in the cniNetDir directory and fix/install the config file if need be. @@ -220,32 +239,44 @@ func (c *Command) directoryWatcher(ctx context.Context, cfg *config.CNIConfig, d // config file is available, do nothing. This can happen if the consul-cni daemonset was // created before other CNI plugins were installed. if event.Op&(fsnotify.Create|fsnotify.Write|fsnotify.Remove) != 0 { - c.logger.Info("Modified event", "event", event) - // Always get the config file that is on the host as we do not know if it was deleted - // or not. - cfgFile, err = defaultCNIConfigFile(dir) - if err != nil { - c.logger.Error("Unable get default config file", "error", err) - break - } - if cfgFile != "" { - c.logger.Info("Using config file", "file", cfgFile) - - err = validConfig(cfg, cfgFile) + // Only repair things if this is a non-multus setup. Multus config is handled differently + // than chained plugins + if !cfg.Multus { + c.logger.Info("Modified event", "event", event) + // Always get the config file that is on the host as we do not know if it was deleted + // or not. + cfgFile, err = defaultCNIConfigFile(dir) if err != nil { - // The invalid config is not critical and we can recover from it. - c.logger.Info("Installing plugin", "reason", err) - err = appendCNIConfig(cfg, cfgFile) + c.logger.Error("Unable get default config file", "error", err) + break + } + + if strings.HasSuffix(cfgFile, ".conf") { + cfgFile, err = confListFileFromConfFile(cfgFile) if err != nil { - c.logger.Error("Unable to install consul-cni config", "error", err) - return err + c.logger.Error("could convert .conf file to .conflist file", "error", err) + break } - } else { - c.logger.Info("Valid config file detected, nothing to do") - break } - } + if cfgFile != "" { + c.logger.Info("Using config file", "file", cfgFile) + + err = validConfig(cfg, cfgFile) + if err != nil { + // The invalid config is not critical and we can recover from it. + c.logger.Info("Installing plugin", "reason", err) + err = appendCNIConfig(cfg, cfgFile) + if err != nil { + c.logger.Error("Unable to install consul-cni config", "error", err) + return err + } + } else { + c.logger.Info("Valid config file detected, nothing to do") + break + } + } + } } case err, ok := <-watcher.Errors: if !ok { diff --git a/control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist b/control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist new file mode 100644 index 0000000000..7f9e222ede --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist @@ -0,0 +1,23 @@ +{ + "cniVersion": "0.3.1", + "name": "k8s-pod-network", + "plugins": [ + { + "binDir": "/opt/multus/bin", + "delegates": [ + { + "cniVersion": "0.3.1", + "name": "openshift-sdn", + "type": "openshift-sdn" + } + ], + "globalNamespaces": "default,openshift-multus,openshift-sriov-network-operator", + "kubeconfig": "/etc/kubernetes/cni/net.d/multus.d/multus.kubeconfig", + "logLevel": "verbose", + "name": "multus-cni-network", + "namespaceIsolation": true, + "readinessindicatorfile": "/var/run/multus/cni/net.d/80-openshift-network.conf", + "type": "multus" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist.golden b/control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist.golden new file mode 100644 index 0000000000..5a7ed53311 --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/00-chained-plugins.conflist.golden @@ -0,0 +1,32 @@ +{ + "cniVersion": "0.3.1", + "name": "k8s-pod-network", + "plugins": [ + { + "binDir": "/opt/multus/bin", + "delegates": [ + { + "cniVersion": "0.3.1", + "name": "openshift-sdn", + "type": "openshift-sdn" + } + ], + "globalNamespaces": "default,openshift-multus,openshift-sriov-network-operator", + "kubeconfig": "/etc/kubernetes/cni/net.d/multus.d/multus.kubeconfig", + "logLevel": "verbose", + "name": "multus-cni-network", + "namespaceIsolation": true, + "readinessindicatorfile": "/var/run/multus/cni/net.d/80-openshift-network.conf", + "type": "multus" + }, + { + "cni_bin_dir": "/var/lib/cni/bin", + "cni_net_dir": "/etc/kubernetes/cni/net.d", + "kubeconfig": "ZZZ-consul-cni-kubeconfig", + "log_level": "info", + "multus": false, + "name": "consul-cni", + "type": "consul-cni" + } + ] +} diff --git a/control-plane/subcommand/install-cni/testdata/00-single-plugin.conf b/control-plane/subcommand/install-cni/testdata/00-single-plugin.conf new file mode 100644 index 0000000000..a111fc091a --- /dev/null +++ b/control-plane/subcommand/install-cni/testdata/00-single-plugin.conf @@ -0,0 +1,18 @@ +{ + "cniVersion": "0.3.1", + "name": "multus-cni-network", + "type": "multus", + "namespaceIsolation": true, + "globalNamespaces": "default,openshift-multus,openshift-sriov-network-operator", + "logLevel": "verbose", + "binDir": "/opt/multus/bin", + "readinessindicatorfile": "/var/run/multus/cni/net.d/80-openshift-network.conf", + "kubeconfig": "/etc/kubernetes/cni/net.d/multus.d/multus.kubeconfig", + "delegates": [ + { + "cniVersion": "0.3.1", + "name": "openshift-sdn", + "type": "openshift-sdn" + } + ] +} From a409655b2ad85dec7f3e2d3cd32ce3702e4a714e Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Mon, 26 Sep 2022 18:48:26 +0000 Subject: [PATCH 136/235] backport of commit 69fe2173c626211490075bbaa66c228c0344c0e6 --- charts/consul/templates/cni-securitycontextconstraints.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/consul/templates/cni-securitycontextconstraints.yaml b/charts/consul/templates/cni-securitycontextconstraints.yaml index 6e76aefd84..95cfc555e1 100644 --- a/charts/consul/templates/cni-securitycontextconstraints.yaml +++ b/charts/consul/templates/cni-securitycontextconstraints.yaml @@ -15,9 +15,9 @@ metadata: to run consul-cni. allowHostDirVolumePlugin: true allowHostIPC: false -allowHostNetwork: true +allowHostNetwork: false allowHostPID: false -allowHostPorts: true +allowHostPorts: false allowPrivilegeEscalation: true allowPrivilegedContainer: true allowedCapabilities: null From 25b3b994967c6bf8226213f1c00b86970184b03a Mon Sep 17 00:00:00 2001 From: Sujata Roy <61177855+20sr20@users.noreply.github.com> Date: Mon, 26 Sep 2022 15:31:47 -0700 Subject: [PATCH 137/235] =?UTF-8?q?create-federation-secret=C2=A0job=20run?= =?UTF-8?q?s=20only=20when=20server.updatePartition=C2=A0is=C2=A00=20(#151?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * create-federation-secret job runs only when server.updatePartition is 0 * I added a test to check createFederationSecret/Job doesn't run when updatepartition != 0 Co-authored-by: David Yu --- CHANGELOG.md | 3 ++- .../templates/create-federation-secret-job.yaml | 2 ++ .../test/unit/create-federation-secret-job.bats | 15 +++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bb0faae72..d6fdfc885d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,8 @@ BUG FIXES: * Control plane * Use global ACL auth method to provision ACL tokens for API Gateway in secondary datacenter [[GH-1481](https://github.com/hashicorp/consul-k8s/pull/1481)] * Helm: - * Fixes a typo in the templating of `global.connectInject.disruptionBudget.maxUnavailable`. [[GH-1530](https://github.com/hashicorp/consul-k8s/pull/1530)]. + * Only create Federation Secret Job when server.updatePartition is 0 [[GH-1512](https://github.com/hashicorp/consul-k8s/pull/1512)] + * Fixes a typo in the templating of `global.connectInject.disruptionBudget.maxUnavailable`. [[GH-1530](https://github.com/hashicorp/consul-k8s/pull/1530)] IMPROVEMENTS: * Helm: diff --git a/charts/consul/templates/create-federation-secret-job.yaml b/charts/consul/templates/create-federation-secret-job.yaml index 3b4333a979..6bc2b9f4d8 100644 --- a/charts/consul/templates/create-federation-secret-job.yaml +++ b/charts/consul/templates/create-federation-secret-job.yaml @@ -1,6 +1,7 @@ {{- if .Values.global.federation.createFederationSecret }} {{- if not .Values.global.federation.enabled }}{{ fail "global.federation.enabled must be true when global.federation.createFederationSecret is true" }}{{ end }} {{- if and (not .Values.global.acls.createReplicationToken) .Values.global.acls.manageSystemACLs }}{{ fail "global.acls.createReplicationToken must be true when global.acls.manageSystemACLs is true because the federation secret must include the replication token" }}{{ end }} +{{- if eq (int .Values.server.updatePartition) 0 }} apiVersion: batch/v1 kind: Job metadata: @@ -157,3 +158,4 @@ spec: memory: "50Mi" cpu: "50m" {{- end }} +{{- end }} diff --git a/charts/consul/test/unit/create-federation-secret-job.bats b/charts/consul/test/unit/create-federation-secret-job.bats index acd493ed78..a3343db582 100644 --- a/charts/consul/test/unit/create-federation-secret-job.bats +++ b/charts/consul/test/unit/create-federation-secret-job.bats @@ -61,6 +61,21 @@ load _helpers [[ "$output" =~ "global.acls.createReplicationToken must be true when global.acls.manageSystemACLs is true because the federation secret must include the replication token" ]] } +@test "createFederationSecret/Job: disabled by updatepartition != 0" { + cd `chart_dir` + assert_empty helm template \ + -s templates/create-federation-secret-job.yaml \ + --set 'global.federation.enabled=true' \ + --set 'global.federation.createFederationSecret=true' \ + --set 'global.acls.createReplicationToken=true' \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.tls.enabled=true' \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'server.updatePartition=1' \ + . +} + @test "createFederationSecret/Job: mounts auto-created ca secrets by default" { cd `chart_dir` local volumes=$(helm template \ From 127577161bb62bfa3f2d6d33ad188c3dc5e573ea Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Mon, 26 Sep 2022 21:17:16 -0700 Subject: [PATCH 138/235] makefile and scripting updates for stable releases (#1526) - Handles case where we are releasing a beta and want that beta release reflected in the changelog --- Makefile | 18 +- control-plane/Makefile | 3 - .../build-support/functions/10-util.sh | 163 ++++++++++-------- control-plane/build-support/scripts/dev.sh | 112 ------------ 4 files changed, 108 insertions(+), 188 deletions(-) delete mode 100755 control-plane/build-support/scripts/dev.sh diff --git a/Makefile b/Makefile index 9d30251581..323bfc96b3 100644 --- a/Makefile +++ b/Makefile @@ -143,13 +143,27 @@ prepare-release: ## Sets the versions, updates changelog to prepare this reposit ifndef RELEASE_VERSION $(error RELEASE_VERSION is required) endif - source $(CURDIR)/control-plane/build-support/scripts/functions.sh; set_release_mode $(CURDIR) $(RELEASE_VERSION) "$(shell date +"%B %d, %Y")" $(PRERELEASE_VERSION) +ifndef RELEASE_DATE + $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) +endif + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_release $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(PRERELEASE_VERSION) +prepare-dev: +ifndef RELEASE_VERSION + $(error RELEASE_VERSION is required) +endif +ifndef RELEASE_DATE + $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) +endif +ifndef NEXT_RELEASE_VERSION + $(error NEXT_RELEASE_VERSION is required) +endif + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_dev $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(NEXT_RELEASE_VERSION) $(PRERELEASE_VERSION) # ===========> Makefile config .DEFAULT_GOAL := help -.PHONY: gen-helm-docs copy-crds-to-chart bats-tests help ci.aws-acceptance-test-cleanup version cli-dev +.PHONY: gen-helm-docs copy-crds-to-chart bats-tests help ci.aws-acceptance-test-cleanup version cli-dev prepare-dev prepare-release SHELL = bash GOOS?=$(shell go env GOOS) GOARCH?=$(shell go env GOARCH) diff --git a/control-plane/Makefile b/control-plane/Makefile index c2177b722f..7dd5ef80d3 100644 --- a/control-plane/Makefile +++ b/control-plane/Makefile @@ -24,9 +24,6 @@ CI_DEV_DOCKER_WORKDIR?=. CONSUL_K8S_IMAGE_VERSION?=latest ################ -ci.dev-tree: - @$(SHELL) $(CURDIR)/build-support/scripts/dev.sh $(DEV_PUSH_ARG) - # TODO: Remove this ci.dev-docker target once we move the acceptance tests to Github Actions. # In CircleCI, the linux binary will be attached from a previous step at pkg/bin/linux_amd64/. This make target # should only run in CI and not locally. diff --git a/control-plane/build-support/functions/10-util.sh b/control-plane/build-support/functions/10-util.sh index fac66227c3..90cfd9660e 100644 --- a/control-plane/build-support/functions/10-util.sh +++ b/control-plane/build-support/functions/10-util.sh @@ -772,7 +772,86 @@ function add_unreleased_to_changelog { return $ret } -function set_release_mode { +function set_version { + # Arguments: + # $1 - Path to top level Consul source + # $2 - The version of the release + # $3 - The release date + # $4 - The pre-release version + # + # + # Returns: + # 0 - success + # * - error + + if ! test -d "$1" + then + err "ERROR: '$1' is not a directory. prepare_release must be called with the path to a git repo as the first argument" + return 1 + fi + + if test -z "$2" + then + err "ERROR: The version specified was empty" + return 1 + fi + + local sdir="$1" + local vers="$2" + + status_stage "==> Updating control-plane version/version.go with version info: ${vers} "$4"" + if ! update_version "${sdir}/control-plane/version/version.go" "${vers}" "$4" + then + unset_changelog_version "${sdir}" + return 1 + fi + + status_stage "==> Updating cli version/version.go with version info: ${vers} "$4"" + if ! update_version "${sdir}/cli/version/version.go" "${vers}" "$4" + then + unset_changelog_version "${sdir}" + return 1 + fi + + status_stage "==> Updating Helm chart versions with version info: ${vers} "$4"" + if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" + then + unset_changelog_version "${sdir}" + return 1 + fi + + return 0 +} + +function set_changelog { + # Arguments: + # $1 - Path to top level Consul source + # $2 - The version of the release + # $3 - The release date + # $4 - The pre-release version + # + # + # Returns: + # 0 - success + # * - error + local sdir="$1" + local vers="$2" + local rel_date="$(date +"%B %d, %Y")" + if test -n "$3" + then + rel_date="$3" + fi + + local changelog_vers="${vers}" + if test -n "$4" + then + changelog_vers="${vers}-$4" + fi + status_stage "==> Updating CHANGELOG.md with release info: ${changelog_vers} (${rel_date})" + set_changelog_version "${sdir}" "${changelog_vers}" "${rel_date}" || return 1 +} + +function prepare_release { # Arguments: # $1 - Path to top level Consul source # $2 - The version of the release @@ -783,90 +862,32 @@ function set_release_mode { # Returns: # 0 - success # * - error - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. set_release_mode must be called with the path to a git repo as the first argument" - return 1 - fi - - echo "release version: " $1 $2 $3 $4 - - if test -z "$2" - then - err "ERROR: The version specified was empty" - return 1 - fi - - local sdir="$1" - local vers="$2" - local rel_date="$(date +"%B %d, %Y")" - - if test -n "$3" - then - rel_date="$3" - fi - - local changelog_vers="${vers}" - if test -n "$4" - then - changelog_vers="${vers}-$4" - fi - - status_stage "==> Updating CHANGELOG.md with release info: ${changelog_vers} (${rel_date})" - set_changelog_version "${sdir}" "${changelog_vers}" "${rel_date}" || return 1 - - status_stage "==> Updating control-plane version/version.go" - if ! update_version "${sdir}/control-plane/version/version.go" "${vers}" "$4" - then - unset_changelog_version "${sdir}" - return 1 - fi - - status_stage "==> Updating cli version/version.go" - if ! update_version "${sdir}/cli/version/version.go" "${vers}" "$4" - then - unset_changelog_version "${sdir}" - return 1 - fi - - status_stage "==> Updating Helm chart versions" - if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" - then - unset_changelog_version "${sdir}" - return 1 - fi - - return 0 + echo "release version: " $1 $2 $3 $4 + set_version "$1" "$2" "$3" "$4" + set_changelog "$1" "$2" "$3" "$4" } -function set_dev_mode { +function prepare_dev { # Arguments: # $1 - Path to top level Consul source + # $2 - The version of the release + # $3 - The release date + # $4 - The version of the next release + # $5 - The pre-release version (for setting beta in changelog) # # Returns: # 0 - success # * - error - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. set_dev_mode must be called with the path to a git repo as the first argument'" - return 1 - fi + echo "dev version: " $1 $4 $3 "dev" local sdir="$1" - local vers="$(parse_version "${sdir}" false false)" - - status_stage "==> Setting VersionPreRelease back to 'dev' for Control Plane" - update_version "${sdir}/version/version.go" "${vers}" dev || return 1 - # This function has been modified for Consul-K8s monorepo. It now sets dev mode - # for the CLI module as well. - status_stage "==> Setting VersionPreRelease back to 'dev' for CLI" - update_version "${sdir}/../cli/version/version.go" "${vers}" dev || return 1 + set_changelog "$1" "$2" "$3" "$5" + set_version "$1" "$4" "$3" "dev" status_stage "==> Adding new UNRELEASED label in CHANGELOG.md" - add_unreleased_to_changelog "${sdir}/.." || return 1 + add_unreleased_to_changelog "${sdir}" || return 1 return 0 } diff --git a/control-plane/build-support/scripts/dev.sh b/control-plane/build-support/scripts/dev.sh deleted file mode 100755 index 7cb79d01e1..0000000000 --- a/control-plane/build-support/scripts/dev.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/bin/bash -SCRIPT_NAME="$(basename ${BASH_SOURCE[0]})" -pushd $(dirname ${BASH_SOURCE[0]}) > /dev/null -SCRIPT_DIR=$(pwd) -pushd ../.. > /dev/null -SOURCE_DIR=$(pwd) -popd > /dev/null -pushd ../functions > /dev/null -FN_DIR=$(pwd) -popd > /dev/null -popd > /dev/null - -source "${SCRIPT_DIR}/functions.sh" - -function usage { -cat <<-EOF -Usage: ${SCRIPT_NAME} [] - -Description: - - This script will put the source back into dev mode after a release. - -Options: - - -s | --source DIR Path to source to build. - Defaults to "${SOURCE_DIR}" - - --no-git Do not commit or attempt to push - the changes back to the upstream. - - -h | --help Print this help text. -EOF -} - -function err_usage { - err "$1" - err "" - err "$(usage)" -} - -function main { - declare sdir="${SOURCE_DIR}" - declare build_os="" - declare build_arch="" - declare -i do_git=1 - declare -i do_push=1 - - - while test $# -gt 0 - do - case "$1" in - -h | --help ) - usage - return 0 - ;; - -s | --source ) - if test -z "$2" - then - err_usage "ERROR: option -s/--source requires an argument" - return 1 - fi - - if ! test -d "$2" - then - err_usage "ERROR: '$2' is not a directory and not suitable for the value of -s/--source" - return 1 - fi - - sdir="$2" - shift 2 - ;; - --no-git ) - do_git=0 - shift - ;; - --no-push ) - do_push=0 - shift - ;; - * ) - err_usage "ERROR: Unknown argument: '$1'" - return 1 - ;; - esac - done - - # Set dev mode for both CLI and Control Plane modules - set_dev_mode "${sdir}" || return 1 - - - if is_set "${do_git}" - then - status_stage "==> Commiting Dev Mode Changes" - # Currently ${sdir} is consul-k8s/control-plane, but for git functions we should be in top-level, so we pass in "${sdir}/..". - # This will commit `version.go` for both CLI and Control Plane modules as well as the CHANGELOG.md. - commit_dev_mode "${sdir}/.." || return 1 - - if is_set "${do_push}" - then - status_stage "==> Confirming Git Changes" - confirm_git_push_changes "${sdir}/.." || return 1 - - status_stage "==> Pushing to Git" - git_push_ref "${sdir}/.." || return 1 - fi - fi - - return 0 -} - -main "$@" -exit $? From d4c3b7d6bf83a9ef51d6d256a5e88aca3ba981ce Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Mon, 26 Sep 2022 21:40:05 -0700 Subject: [PATCH 139/235] fix spacing so ifndef has expected behavior (#1536) --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 323bfc96b3..43a8e16b0d 100644 --- a/Makefile +++ b/Makefile @@ -144,7 +144,7 @@ ifndef RELEASE_VERSION $(error RELEASE_VERSION is required) endif ifndef RELEASE_DATE - $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) + $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) endif source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_release $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(PRERELEASE_VERSION) @@ -153,7 +153,7 @@ ifndef RELEASE_VERSION $(error RELEASE_VERSION is required) endif ifndef RELEASE_DATE - $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) + $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) endif ifndef NEXT_RELEASE_VERSION $(error NEXT_RELEASE_VERSION is required) From c220618008d48d1a2476204c4667da28705a5521 Mon Sep 17 00:00:00 2001 From: Kyle Schochenmaier Date: Tue, 27 Sep 2022 10:06:44 -0500 Subject: [PATCH 140/235] Support escaped commas in service tags for connect (#1532) * support escaped commas in service tag annotations --- CHANGELOG.md | 2 + control-plane/catalog/to-consul/resource.go | 53 +----------------- .../catalog/to-consul/resource_test.go | 44 --------------- .../connect-inject/endpoints_controller.go | 5 +- .../endpoints_controller_test.go | 8 +-- control-plane/helper/parsetags/parsetags.go | 56 +++++++++++++++++++ .../helper/parsetags/parsetags_test.go | 51 +++++++++++++++++ 7 files changed, 118 insertions(+), 101 deletions(-) create mode 100644 control-plane/helper/parsetags/parsetags.go create mode 100644 control-plane/helper/parsetags/parsetags_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index d6fdfc885d..f94f2ae210 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ BUG FIXES: IMPROVEMENTS: * Helm: * API Gateway: Set primary datacenter flag when deploying controller into secondary datacenter with federation enabled [[GH-1511](https://github.com/hashicorp/consul-k8s/pull/1511)] +* Control-plane: + * Support escaped commas in service tag annotations for pods which use `consul.hashicorp.com/connect-service-tags` or `consul.hashicorp.com/service-tags`. [[GH-1532](https://github.com/hashicorp/consul-k8s/pull/1532)] ## 0.48.0 (September 01, 2022) diff --git a/control-plane/catalog/to-consul/resource.go b/control-plane/catalog/to-consul/resource.go index 03de1d26bb..239e2f5db9 100644 --- a/control-plane/catalog/to-consul/resource.go +++ b/control-plane/catalog/to-consul/resource.go @@ -9,6 +9,7 @@ import ( mapset "github.com/deckarep/golang-set" "github.com/hashicorp/consul-k8s/control-plane/helper/controller" + "github.com/hashicorp/consul-k8s/control-plane/helper/parsetags" "github.com/hashicorp/consul-k8s/control-plane/namespaces" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/go-hclog" @@ -438,7 +439,7 @@ func (t *ServiceResource) generateRegistrations(key string) { // Parse any additional tags if rawTags, ok := svc.Annotations[annotationServiceTags]; ok { - baseService.Tags = append(baseService.Tags, parseTags(rawTags)...) + baseService.Tags = append(baseService.Tags, parsetags.ParseTags(rawTags)...) } // Parse any additional meta @@ -787,53 +788,3 @@ func (t *ServiceResource) addPrefixAndK8SNamespace(name, namespace string) strin return name } - -// parseTags parses the tags annotation into a slice of tags. -// Tags are split on commas (except for escaped commas "\,"). -func parseTags(tagsAnno string) []string { - - // This algorithm parses the tagsAnno string into a slice of strings. - // Ideally we'd just split on commas but since Consul tags support commas, - // we allow users to escape commas so they're included in the tag, e.g. - // the annotation "tag\,with\,commas,tag2" will become the tags: - // ["tag,with,commas", "tag2"]. - - var tags []string - // nextTag is built up char by char until we see a comma. Then we - // append it to tags. - var nextTag string - - for _, runeChar := range tagsAnno { - runeStr := fmt.Sprintf("%c", runeChar) - - // Not a comma, just append to nextTag. - if runeStr != "," { - nextTag += runeStr - continue - } - - // Reached a comma but there's nothing in nextTag, - // skip. (e.g. "a,,b" => ["a", "b"]) - if len(nextTag) == 0 { - continue - } - - // Check if the comma was escaped comma, e.g. "a\,b". - if string(nextTag[len(nextTag)-1]) == `\` { - // Replace the backslash with a comma. - nextTag = nextTag[0:len(nextTag)-1] + "," - continue - } - - // Non-escaped comma. We're ready to push nextTag onto tags and reset nextTag. - tags = append(tags, strings.TrimSpace(nextTag)) - nextTag = "" - } - - // We're done the loop but nextTag still contains the last tag. - if len(nextTag) > 0 { - tags = append(tags, strings.TrimSpace(nextTag)) - } - - return tags -} diff --git a/control-plane/catalog/to-consul/resource_test.go b/control-plane/catalog/to-consul/resource_test.go index 1a4203725a..28335dea27 100644 --- a/control-plane/catalog/to-consul/resource_test.go +++ b/control-plane/catalog/to-consul/resource_test.go @@ -1490,50 +1490,6 @@ func TestServiceResource_MirroredPrefixNamespace(t *testing.T) { }) } -func TestParseTags(t *testing.T) { - cases := []struct { - tagsAnno string - exp []string - }{ - { - "tag", - []string{"tag"}, - }, - { - ",,removes,,empty,elems,,", - []string{"removes", "empty", "elems"}, - }, - { - "removes , white ,space ", - []string{"removes", "white", "space"}, - }, - { - `\,leading,comma`, - []string{",leading", "comma"}, - }, - { - `trailing,comma\,`, - []string{"trailing", "comma,"}, - }, - { - `mid\,dle,com\,ma`, - []string{"mid,dle", "com,ma"}, - }, - { - `\,\,multi\,\,,\,com\,\,ma`, - []string{",,multi,,", ",com,,ma"}, - }, - { - ` every\,\, , thing `, - []string{"every,,", "thing"}, - }, - } - - for _, c := range cases { - require.Equal(t, c.exp, parseTags(c.tagsAnno)) - } -} - // lbService returns a Kubernetes service of type LoadBalancer. func lbService(name, namespace, lbIP string) *apiv1.Service { return &apiv1.Service{ diff --git a/control-plane/connect-inject/endpoints_controller.go b/control-plane/connect-inject/endpoints_controller.go index 04c8e70a26..9b37ca3bcf 100644 --- a/control-plane/connect-inject/endpoints_controller.go +++ b/control-plane/connect-inject/endpoints_controller.go @@ -13,6 +13,7 @@ import ( mapset "github.com/deckarep/golang-set" "github.com/go-logr/logr" "github.com/hashicorp/consul-k8s/control-plane/consul" + "github.com/hashicorp/consul-k8s/control-plane/helper/parsetags" "github.com/hashicorp/consul-k8s/control-plane/namespaces" "github.com/hashicorp/consul/api" "github.com/hashicorp/go-multierror" @@ -1213,11 +1214,11 @@ func isLabeledIgnore(labels map[string]string) bool { func consulTags(pod corev1.Pod) []string { var tags []string if raw, ok := pod.Annotations[annotationTags]; ok && raw != "" { - tags = strings.Split(raw, ",") + tags = append(tags, parsetags.ParseTags(raw)...) } // Get the tags from the deprecated tags annotation and combine. if raw, ok := pod.Annotations[annotationConnectTags]; ok && raw != "" { - tags = append(tags, strings.Split(raw, ",")...) + tags = append(tags, parsetags.ParseTags(raw)...) } var interpolatedTags []string diff --git a/control-plane/connect-inject/endpoints_controller_test.go b/control-plane/connect-inject/endpoints_controller_test.go index 19cda9a206..abbad4b2a6 100644 --- a/control-plane/connect-inject/endpoints_controller_test.go +++ b/control-plane/connect-inject/endpoints_controller_test.go @@ -1522,8 +1522,8 @@ func TestReconcileCreateEndpoint(t *testing.T) { pod1.Annotations[fmt.Sprintf("%sname", annotationMeta)] = "abc" pod1.Annotations[fmt.Sprintf("%sversion", annotationMeta)] = "2" pod1.Annotations[fmt.Sprintf("%spod_name", annotationMeta)] = "$POD_NAME" - pod1.Annotations[annotationTags] = "abc,123,$POD_NAME" - pod1.Annotations[annotationConnectTags] = "def,456,$POD_NAME" + pod1.Annotations[annotationTags] = "abc\\,123,$POD_NAME" + pod1.Annotations[annotationConnectTags] = "def\\,456,$POD_NAME" pod1.Annotations[annotationUpstreams] = "upstream1:1234" pod1.Annotations[annotationEnableMetrics] = "true" pod1.Annotations[annotationPrometheusScrapePort] = "12345" @@ -1567,7 +1567,7 @@ func TestReconcileCreateEndpoint(t *testing.T) { MetaKeyKubeNS: "default", MetaKeyManagedBy: managedByValue, }, - ServiceTags: []string{"abc", "123", "pod1", "def", "456", "pod1"}, + ServiceTags: []string{"abc,123", "pod1", "def,456", "pod1"}, }, }, expectedProxySvcInstances: []*api.CatalogService{ @@ -1601,7 +1601,7 @@ func TestReconcileCreateEndpoint(t *testing.T) { MetaKeyKubeNS: "default", MetaKeyManagedBy: managedByValue, }, - ServiceTags: []string{"abc", "123", "pod1", "def", "456", "pod1"}, + ServiceTags: []string{"abc,123", "pod1", "def,456", "pod1"}, }, }, expectedAgentHealthChecks: []*api.AgentCheck{ diff --git a/control-plane/helper/parsetags/parsetags.go b/control-plane/helper/parsetags/parsetags.go new file mode 100644 index 0000000000..e9d9625338 --- /dev/null +++ b/control-plane/helper/parsetags/parsetags.go @@ -0,0 +1,56 @@ +package parsetags + +import ( + "fmt" + "strings" +) + +// ParseTags parses the tags annotation into a slice of tags. +// Tags are split on commas (except for escaped commas "\,"). +func ParseTags(tagsAnno string) []string { + + // This algorithm parses the tagsAnno string into a slice of strings. + // Ideally we'd just split on commas but since Consul tags support commas, + // we allow users to escape commas so they're included in the tag, e.g. + // the annotation "tag\,with\,commas,tag2" will become the tags: + // ["tag,with,commas", "tag2"]. + + var tags []string + // nextTag is built up char by char until we see a comma. Then we + // append it to tags. + var nextTag string + + for _, runeChar := range tagsAnno { + runeStr := fmt.Sprintf("%c", runeChar) + + // Not a comma, just append to nextTag. + if runeStr != "," { + nextTag += runeStr + continue + } + + // Reached a comma but there's nothing in nextTag, + // skip. (e.g. "a,,b" => ["a", "b"]) + if len(nextTag) == 0 { + continue + } + + // Check if the comma was escaped comma, e.g. "a\,b". + if string(nextTag[len(nextTag)-1]) == `\` { + // Replace the backslash with a comma. + nextTag = nextTag[0:len(nextTag)-1] + "," + continue + } + + // Non-escaped comma. We're ready to push nextTag onto tags and reset nextTag. + tags = append(tags, strings.TrimSpace(nextTag)) + nextTag = "" + } + + // We're done the loop but nextTag still contains the last tag. + if len(nextTag) > 0 { + tags = append(tags, strings.TrimSpace(nextTag)) + } + + return tags +} diff --git a/control-plane/helper/parsetags/parsetags_test.go b/control-plane/helper/parsetags/parsetags_test.go new file mode 100644 index 0000000000..f403a2f711 --- /dev/null +++ b/control-plane/helper/parsetags/parsetags_test.go @@ -0,0 +1,51 @@ +package parsetags + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseTags(t *testing.T) { + cases := []struct { + tagsAnno string + exp []string + }{ + { + "tag", + []string{"tag"}, + }, + { + ",,removes,,empty,elems,,", + []string{"removes", "empty", "elems"}, + }, + { + "removes , white ,space ", + []string{"removes", "white", "space"}, + }, + { + `\,leading,comma`, + []string{",leading", "comma"}, + }, + { + `trailing,comma\,`, + []string{"trailing", "comma,"}, + }, + { + `mid\,dle,com\,ma`, + []string{"mid,dle", "com,ma"}, + }, + { + `\,\,multi\,\,,\,com\,\,ma`, + []string{",,multi,,", ",com,,ma"}, + }, + { + ` every\,\, , thing `, + []string{"every,,", "thing"}, + }, + } + + for _, c := range cases { + require.Equal(t, c.exp, ParseTags(c.tagsAnno)) + } +} From c6811ed9922d87e18d5f68b90c2ee4142ae9f955 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Tue, 27 Sep 2022 15:18:58 +0000 Subject: [PATCH 141/235] backport of commit d46addf3432f18248aab321b310687a7d7503dce --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e8b1f01dd..1bb771889b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ FEATURES: * CLI: * Add support for tab autocompletion [[GH-1437](https://github.com/hashicorp/consul-k8s/pull/1501)] +* Consul CNI Plugin + * Support for OpenShift and Multus CNI plugin [[GH-1527](https://github.com/hashicorp/consul-k8s/pull/1527)] BUG FIXES: * Control plane From 5c406683f19e987686c6cf597aa634508e866f2a Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Tue, 27 Sep 2022 11:47:41 -0400 Subject: [PATCH 142/235] 0.49.0 Pre-release (#1538) --- charts/consul/Chart.yaml | 4 ++-- charts/consul/values.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index a2209ac9b6..b5b5741d03 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul version: 0.48.0 -appVersion: 1.13.1 +appVersion: 1.13.2 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -13,7 +13,7 @@ annotations: artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.13.1 + image: hashicorp/consul:1.13.2 - name: consul-k8s-control-plane image: hashicorp/consul-k8s-control-plane:0.48.0 - name: envoy diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index cfe87e1205..d90b98d2b5 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -109,7 +109,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.13.1" + image: "hashicorp/consul:1.13.2" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. From ff3d477a7e4bf0f6cb2657788a34a77ceb7ecf62 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Tue, 27 Sep 2022 11:55:06 -0400 Subject: [PATCH 143/235] Initial 0.49.0 branch creation --- CHANGELOG.md | 2 +- charts/consul/Chart.yaml | 4 ++-- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f94f2ae210..5e8b1f01dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.49.0 (September 29, 2022) FEATURES: * CLI: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index b5b5741d03..8b7e2da587 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.48.0 +version: 0.49.0 appVersion: 1.13.2 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -15,7 +15,7 @@ annotations: - name: consul image: hashicorp/consul:1.13.2 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.48.0 + image: hashicorp/consul-k8s-control-plane:0.49.0 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index d90b98d2b5..72b447814c 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.48.0 + imageK8S: hashicorp/consul-k8s-control-plane:0.49.0 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index b74b5fa468..082ffeb1f3 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.48.0" + Version = "0.49.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index b74b5fa468..082ffeb1f3 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.48.0" + Version = "0.49.0" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 8c0354b6dfaf11a25b605d9f949d4b7e4f1223fc Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Thu, 22 Sep 2022 21:27:53 +0000 Subject: [PATCH 144/235] backport of commit 96cba089e378f30a3fad4c829ad44d712e4f841a --- charts/consul/templates/api-gateway-controller-clusterrole.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/charts/consul/templates/api-gateway-controller-clusterrole.yaml b/charts/consul/templates/api-gateway-controller-clusterrole.yaml index 5253fd349c..cce6b5b6c6 100644 --- a/charts/consul/templates/api-gateway-controller-clusterrole.yaml +++ b/charts/consul/templates/api-gateway-controller-clusterrole.yaml @@ -92,8 +92,10 @@ rules: resources: - secrets verbs: + - create - get - list + - update - watch - apiGroups: - "" From cdcec47e29d26f732a3ecfcbdf0133374075a6ef Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Tue, 27 Sep 2022 18:36:28 +0000 Subject: [PATCH 145/235] backport of commit b3fcc2876a6fd82457089e114c4140168aa1d9db --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bb771889b..e45b5064e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ BUG FIXES: IMPROVEMENTS: * Helm: * API Gateway: Set primary datacenter flag when deploying controller into secondary datacenter with federation enabled [[GH-1511](https://github.com/hashicorp/consul-k8s/pull/1511)] + * API Gateway: Allow controller to create and update Secrets in order to support distroless Envoy images [[GH-1542](https://github.com/hashicorp/consul-k8s/pull/1542)] * Control-plane: * Support escaped commas in service tag annotations for pods which use `consul.hashicorp.com/connect-service-tags` or `consul.hashicorp.com/service-tags`. [[GH-1532](https://github.com/hashicorp/consul-k8s/pull/1532)] From 0945438efeaf83c18610bf751fff598e64d935b1 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Tue, 27 Sep 2022 22:51:02 +0000 Subject: [PATCH 146/235] backport of commit 5d07c8dc43d4d123fbc731d62991b827937c1409 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e45b5064e1..1ebb6db2aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ BUG FIXES: IMPROVEMENTS: * Helm: * API Gateway: Set primary datacenter flag when deploying controller into secondary datacenter with federation enabled [[GH-1511](https://github.com/hashicorp/consul-k8s/pull/1511)] - * API Gateway: Allow controller to create and update Secrets in order to support distroless Envoy images [[GH-1542](https://github.com/hashicorp/consul-k8s/pull/1542)] + * API Gateway: Allow controller to create and update Secrets for storing Consul CA cert alongside gateway Deployments [[GH-1542](https://github.com/hashicorp/consul-k8s/pull/1542)] * Control-plane: * Support escaped commas in service tag annotations for pods which use `consul.hashicorp.com/connect-service-tags` or `consul.hashicorp.com/service-tags`. [[GH-1532](https://github.com/hashicorp/consul-k8s/pull/1532)] From f6c3d1bc22f27c9218286472cbb414d599b7c5bd Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Tue, 27 Sep 2022 23:52:32 +0000 Subject: [PATCH 147/235] backport of commit 4a0bd4eea0627103fe0c2d34b2cd4a82f402e213 --- charts/consul/templates/client-daemonset.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/consul/templates/client-daemonset.yaml b/charts/consul/templates/client-daemonset.yaml index 1a51d69b90..36edc70ddb 100644 --- a/charts/consul/templates/client-daemonset.yaml +++ b/charts/consul/templates/client-daemonset.yaml @@ -294,6 +294,7 @@ spec: {{- if .Values.global.tls.enableAutoEncrypt }} -hcl='auto_encrypt = {tls = true}' \ -hcl="auto_encrypt = {ip_san = [\"$HOST_IP\",\"$POD_IP\"]}" \ + -hcl='tls { grpc { use_auto_cert = true } }' \ {{- else }} -hcl='tls { defaults { cert_file = "/consul/tls/client/tls.crt" }}' \ -hcl='tls { defaults { key_file = "/consul/tls/client/tls.key" }}' \ From 317db6cde55c70c576d47e4a6b53ac45a7ae6fa3 Mon Sep 17 00:00:00 2001 From: Iryna Shustava Date: Wed, 28 Sep 2022 15:01:16 +0000 Subject: [PATCH 148/235] backport of commit 5e6203de5ae0ef98c2595e1e9e53e7b215d7ff37 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ebb6db2aa..4aa1aab8ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ FEATURES: BUG FIXES: * Control plane * Use global ACL auth method to provision ACL tokens for API Gateway in secondary datacenter [[GH-1481](https://github.com/hashicorp/consul-k8s/pull/1481)] + * Peering: pass new `use_auto_cert` value to gRPC TLS config when auto-encrypt is enabled. [[GH-1541](https://github.com/hashicorp/consul-k8s/pull/1541)] * Helm: * Only create Federation Secret Job when server.updatePartition is 0 [[GH-1512](https://github.com/hashicorp/consul-k8s/pull/1512)] * Fixes a typo in the templating of `global.connectInject.disruptionBudget.maxUnavailable`. [[GH-1530](https://github.com/hashicorp/consul-k8s/pull/1530)] From ce1af951bb5fce56f5df96ae1f39b96802554e12 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Wed, 28 Sep 2022 11:25:34 -0700 Subject: [PATCH 149/235] backport of commit 8f50af6e3487b3f436f9ac6f613dbecaf64f0265 (#1550) This pull request was automerged via backport-assistant --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index c1548332e0..fe0070c1c9 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -14,7 +14,7 @@ jobs: container: hashicorpdev/backport-assistant:0.2.5 steps: - name: Run Backport Assistant - run: backport-assistant backport -automerge + run: backport-assistant backport -automerge -merge-method=squash env: BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+\\.x)" BACKPORT_TARGET_TEMPLATE: "release/{{.target}}" From f135465e4d9dfd36d8e1921b8287b3b9c15600c5 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Thu, 29 Sep 2022 10:52:33 -0700 Subject: [PATCH 150/235] backport of [1484](https://github.com/hashicorp/consul-k8s/pull/1484) (#1562) Co-authored-by: malizz --- .../bases/crds-oss/servicedefaults.yaml | 1 + .../consul/templates/crd-servicedefaults.yaml | 14 ++++++ .../api/v1alpha1/servicedefaults_types.go | 10 +++- .../v1alpha1/servicedefaults_types_test.go | 49 ++++++++++++------- .../consul.hashicorp.com_servicedefaults.yaml | 14 ++++++ control-plane/go.mod | 19 +++---- control-plane/go.sum | 40 ++++++++------- 7 files changed, 99 insertions(+), 48 deletions(-) diff --git a/acceptance/tests/fixtures/bases/crds-oss/servicedefaults.yaml b/acceptance/tests/fixtures/bases/crds-oss/servicedefaults.yaml index 6256790a80..7b5f23eff5 100644 --- a/acceptance/tests/fixtures/bases/crds-oss/servicedefaults.yaml +++ b/acceptance/tests/fixtures/bases/crds-oss/servicedefaults.yaml @@ -18,6 +18,7 @@ spec: passiveHealthCheck: interval: 1s maxFailures: 10 + enforcing_consecutive_5xx: 60 - name: "bar" limits: maxConnections: 5 diff --git a/charts/consul/templates/crd-servicedefaults.yaml b/charts/consul/templates/crd-servicedefaults.yaml index f0ba18a616..636e8ce51f 100644 --- a/charts/consul/templates/crd-servicedefaults.yaml +++ b/charts/consul/templates/crd-servicedefaults.yaml @@ -241,6 +241,13 @@ spec: upstream proxy instances will be monitored for removal from the load balancing pool. properties: + enforcing_consecutive_5xx: + description: EnforcingConsecutive5xx is the % chance that + a host will be actually ejected when an outlier status + is detected through consecutive 5xx. This setting can + be used to disable ejection or to ramp it up slowly. + format: int32 + type: integer interval: description: Interval between health check analysis sweeps. Each sweep may remove hosts or return hosts to the pool. @@ -333,6 +340,13 @@ spec: how upstream proxy instances will be monitored for removal from the load balancing pool. properties: + enforcing_consecutive_5xx: + description: EnforcingConsecutive5xx is the % chance + that a host will be actually ejected when an outlier + status is detected through consecutive 5xx. This setting + can be used to disable ejection or to ramp it up slowly. + format: int32 + type: integer interval: description: Interval between health check analysis sweeps. Each sweep may remove hosts or return hosts diff --git a/control-plane/api/v1alpha1/servicedefaults_types.go b/control-plane/api/v1alpha1/servicedefaults_types.go index 325b80cefe..b3902c4118 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types.go +++ b/control-plane/api/v1alpha1/servicedefaults_types.go @@ -160,6 +160,10 @@ type PassiveHealthCheck struct { // MaxFailures is the count of consecutive failures that results in a host // being removed from the pool. MaxFailures uint32 `json:"maxFailures,omitempty"` + // EnforcingConsecutive5xx is the % chance that a host will be actually ejected + // when an outlier status is detected through consecutive 5xx. + // This setting can be used to disable ejection or to ramp it up slowly. + EnforcingConsecutive5xx *uint32 `json:"enforcing_consecutive_5xx,omitempty"` } type ServiceDefaultsDestination struct { @@ -386,9 +390,11 @@ func (in *PassiveHealthCheck) toConsul() *capi.PassiveHealthCheck { if in == nil { return nil } + return &capi.PassiveHealthCheck{ - Interval: in.Interval.Duration, - MaxFailures: in.MaxFailures, + Interval: in.Interval.Duration, + MaxFailures: in.MaxFailures, + EnforcingConsecutive5xx: in.EnforcingConsecutive5xx, } } diff --git a/control-plane/api/v1alpha1/servicedefaults_types_test.go b/control-plane/api/v1alpha1/servicedefaults_types_test.go index 6c15c00c48..c70c8a6408 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types_test.go +++ b/control-plane/api/v1alpha1/servicedefaults_types_test.go @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" ) func TestServiceDefaults_ToConsul(t *testing.T) { @@ -82,7 +83,8 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Interval: metav1.Duration{ Duration: 2 * time.Second, }, - MaxFailures: uint32(20), + MaxFailures: uint32(20), + EnforcingConsecutive5xx: pointer.Uint32(100), }, MeshGateway: MeshGateway{ Mode: "local", @@ -106,7 +108,8 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Interval: metav1.Duration{ Duration: 2 * time.Second, }, - MaxFailures: uint32(10), + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: MeshGateway{ Mode: "remote", @@ -129,7 +132,8 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Interval: metav1.Duration{ Duration: 2 * time.Second, }, - MaxFailures: uint32(10), + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: MeshGateway{ Mode: "remote", @@ -188,8 +192,9 @@ func TestServiceDefaults_ToConsul(t *testing.T) { MaxConcurrentRequests: intPointer(10), }, PassiveHealthCheck: &capi.PassiveHealthCheck{ - Interval: 2 * time.Second, - MaxFailures: uint32(20), + Interval: 2 * time.Second, + MaxFailures: uint32(20), + EnforcingConsecutive5xx: pointer.Uint32(100), }, MeshGateway: capi.MeshGatewayConfig{ Mode: "local", @@ -210,8 +215,9 @@ func TestServiceDefaults_ToConsul(t *testing.T) { MaxConcurrentRequests: intPointer(5), }, PassiveHealthCheck: &capi.PassiveHealthCheck{ - Interval: 2 * time.Second, - MaxFailures: uint32(10), + Interval: 2 * time.Second, + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: capi.MeshGatewayConfig{ Mode: "remote", @@ -231,8 +237,9 @@ func TestServiceDefaults_ToConsul(t *testing.T) { MaxConcurrentRequests: intPointer(2), }, PassiveHealthCheck: &capi.PassiveHealthCheck{ - Interval: 2 * time.Second, - MaxFailures: uint32(10), + Interval: 2 * time.Second, + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: capi.MeshGatewayConfig{ Mode: "remote", @@ -335,7 +342,8 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { Interval: metav1.Duration{ Duration: 2 * time.Second, }, - MaxFailures: uint32(20), + MaxFailures: uint32(20), + EnforcingConsecutive5xx: pointer.Uint32(100), }, MeshGateway: MeshGateway{ Mode: "local", @@ -358,7 +366,8 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { Interval: metav1.Duration{ Duration: 2 * time.Second, }, - MaxFailures: uint32(10), + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: MeshGateway{ Mode: "remote", @@ -380,7 +389,8 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { Interval: metav1.Duration{ Duration: 2 * time.Second, }, - MaxFailures: uint32(10), + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: MeshGateway{ Mode: "remote", @@ -436,8 +446,9 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { MaxConcurrentRequests: intPointer(10), }, PassiveHealthCheck: &capi.PassiveHealthCheck{ - Interval: 2 * time.Second, - MaxFailures: uint32(20), + Interval: 2 * time.Second, + MaxFailures: uint32(20), + EnforcingConsecutive5xx: pointer.Uint32(100), }, MeshGateway: capi.MeshGatewayConfig{ Mode: "local", @@ -457,8 +468,9 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { MaxConcurrentRequests: intPointer(5), }, PassiveHealthCheck: &capi.PassiveHealthCheck{ - Interval: 2 * time.Second, - MaxFailures: uint32(10), + Interval: 2 * time.Second, + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: capi.MeshGatewayConfig{ Mode: "remote", @@ -477,8 +489,9 @@ func TestServiceDefaults_MatchesConsul(t *testing.T) { MaxConcurrentRequests: intPointer(2), }, PassiveHealthCheck: &capi.PassiveHealthCheck{ - Interval: 2 * time.Second, - MaxFailures: uint32(10), + Interval: 2 * time.Second, + MaxFailures: uint32(10), + EnforcingConsecutive5xx: pointer.Uint32(60), }, MeshGateway: capi.MeshGatewayConfig{ Mode: "remote", diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml index 67f33517ba..ae815fce47 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml @@ -234,6 +234,13 @@ spec: upstream proxy instances will be monitored for removal from the load balancing pool. properties: + enforcing_consecutive_5xx: + description: EnforcingConsecutive5xx is the % chance that + a host will be actually ejected when an outlier status + is detected through consecutive 5xx. This setting can + be used to disable ejection or to ramp it up slowly. + format: int32 + type: integer interval: description: Interval between health check analysis sweeps. Each sweep may remove hosts or return hosts to the pool. @@ -326,6 +333,13 @@ spec: how upstream proxy instances will be monitored for removal from the load balancing pool. properties: + enforcing_consecutive_5xx: + description: EnforcingConsecutive5xx is the % chance + that a host will be actually ejected when an outlier + status is detected through consecutive 5xx. This setting + can be used to disable ejection or to ramp it up slowly. + format: int32 + type: integer interval: description: Interval between health check analysis sweeps. Each sweep may remove hosts or return hosts diff --git a/control-plane/go.mod b/control-plane/go.mod index 50b1c65a2e..8d0f894729 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -8,10 +8,11 @@ require ( github.com/go-logr/logr v0.4.0 github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 + github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 + github.com/hashicorp/consul/api v1.10.1-0.20220913205944-e743eefbd104 github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f - github.com/hashicorp/go-hclog v0.16.1 + github.com/hashicorp/go-hclog v1.2.2 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/serf v0.9.7 github.com/kr/text v0.2.0 @@ -19,7 +20,7 @@ require ( github.com/mitchellh/cli v1.1.0 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.4.1 - github.com/stretchr/testify v1.7.1 + github.com/stretchr/testify v1.7.2 go.uber.org/zap v1.19.0 golang.org/x/text v0.3.7 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 @@ -51,13 +52,12 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/containernetworking/plugins v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 // indirect github.com/digitalocean/godo v1.10.0 // indirect github.com/dimchansky/utfbom v1.1.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/fatih/color v1.12.0 // indirect + github.com/fatih/color v1.13.0 // indirect github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect github.com/go-logr/zapr v0.4.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -69,7 +69,6 @@ require ( github.com/googleapis/gax-go/v2 v2.0.5 // indirect github.com/googleapis/gnostic v0.5.5 // indirect github.com/gophercloud/gophercloud v0.1.0 // indirect - github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.0 // indirect @@ -117,12 +116,12 @@ require ( google.golang.org/api v0.43.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect - google.golang.org/grpc v1.38.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect + google.golang.org/grpc v1.48.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/resty.v1 v1.12.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apiextensions-apiserver v0.22.2 // indirect k8s.io/component-base v0.22.2 // indirect k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect @@ -130,6 +129,4 @@ require ( sigs.k8s.io/yaml v1.2.0 // indirect ) -replace github.com/hashicorp/consul/sdk v0.10.0 => github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51 - go 1.18 diff --git a/control-plane/go.sum b/control-plane/go.sum index 3d48c2626a..00ee1f4970 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -132,14 +132,16 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA= github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI= github.com/containernetworking/cni v1.1.1 h1:ky20T7c0MvKvbMOwS/FrlbNwjEoqJEUUYfsL4b0mc4k= github.com/containernetworking/cni v1.1.1/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= -github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNGz0C1d3wVYlHE= -github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -182,6 +184,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -190,8 +193,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= @@ -286,6 +289,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -335,15 +339,13 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2 github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a h1:cBwGTYV84M0W8PwHX6+PywY8NiP3dzA7JaZzs9+LdiA= -github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220824032443-9606072aec2a/go.mod h1:aw35GB76URgbtxaSSMxbOetbG7YEHHPkIX3/SkTBaWc= github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 h1:TQY0oKtLV15UNYWeSkTxi4McBIyLecsEtbc/VfxvbYA= github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8/go.mod h1:aw35GB76URgbtxaSSMxbOetbG7YEHHPkIX3/SkTBaWc= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35 h1:csNww5qBHaFqsX1eMEKVvmJ4dhqcXWj0sCkbccsSsHc= -github.com/hashicorp/consul/api v1.10.1-0.20220822180451-60c82757ea35/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.10.1-0.20220913205944-e743eefbd104 h1:NW0jZq0suX2gfHVFmKuJ5DGLXSP7qN9FmjQOU764fFQ= +github.com/hashicorp/consul/api v1.10.1-0.20220913205944-e743eefbd104/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.4.1-0.20220801192236-988e1fd35d51/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= +github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -356,8 +358,8 @@ github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f h1:7WFMVeuJQ github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f/go.mod h1:D4eo8/CN92vm9/9UDG+ldX1/fMFa4kpl8qzyTolus8o= github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v0.16.1 h1:IVQwpTGNRRIHafnTs2dQLIk4ENtneRIEEJWOVDqz99o= -github.com/hashicorp/go-hclog v0.16.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= +github.com/hashicorp/go-hclog v1.2.2 h1:ihRI7YFwcZdiSD7SIenIhHfQH3OuDvWerAUBZbeQS3M= +github.com/hashicorp/go-hclog v1.2.2/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.0 h1:8exGP7ego3OmkfksihtSouGMZ+hQrhxx+FVELeXpVPE= github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -460,7 +462,7 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -632,8 +634,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible h1:8uRvJleFpqLsO77WaAh2UrasMOzd8MxXrNj20e7El+Q= github.com/tencentcloud/tencentcloud-sdk-go v3.0.83+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4= @@ -897,6 +899,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I= golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1084,8 +1087,9 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= +google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1098,8 +1102,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1131,8 +1136,9 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 6d23642d41c363adb199ac89e7dc4e05d740798c Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 29 Sep 2022 19:22:47 +0000 Subject: [PATCH 151/235] backport of commit 0f9f738e101bb8fd1c09a928bb7d163fa4dab61e --- .github/workflows/backport.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index fe0070c1c9..c1548332e0 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -14,7 +14,7 @@ jobs: container: hashicorpdev/backport-assistant:0.2.5 steps: - name: Run Backport Assistant - run: backport-assistant backport -automerge -merge-method=squash + run: backport-assistant backport -automerge env: BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+\\.x)" BACKPORT_TARGET_TEMPLATE: "release/{{.target}}" From b8443b4af3e486c9652abded1207a43300da48e8 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Thu, 29 Sep 2022 14:34:39 -0700 Subject: [PATCH 152/235] cherry picked changes (#1564) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aa1aab8ca..c47707de59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ IMPROVEMENTS: * Helm: * API Gateway: Set primary datacenter flag when deploying controller into secondary datacenter with federation enabled [[GH-1511](https://github.com/hashicorp/consul-k8s/pull/1511)] * API Gateway: Allow controller to create and update Secrets for storing Consul CA cert alongside gateway Deployments [[GH-1542](https://github.com/hashicorp/consul-k8s/pull/1542)] + * New parameter `EnforcingConsecutive5xx` which supports a configurable percent chance of automatic ejection of a host when a consecutive number of 5xx response codes are received [[GH-1484](https://github.com/hashicorp/consul-k8s/pull/1484)] * Control-plane: * Support escaped commas in service tag annotations for pods which use `consul.hashicorp.com/connect-service-tags` or `consul.hashicorp.com/service-tags`. [[GH-1532](https://github.com/hashicorp/consul-k8s/pull/1532)] From 5a7ada943d26a2c6189aa68e63a03bb743be47f6 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Thu, 29 Sep 2022 22:54:12 -0400 Subject: [PATCH 153/235] Set Sept 30th as release date for 0.49.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c47707de59..a3764c5a52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.49.0 (September 29, 2022) +## 0.49.0 (September 30, 2022) FEATURES: * CLI: From 0a2cf9aee0d3f1a8b6691aab39fde35d8a5b5507 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Fri, 30 Sep 2022 09:49:34 -0400 Subject: [PATCH 154/235] Trigger the pre-staging release of artifacts (#1569) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3764c5a52..d292b2306b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1594,3 +1594,4 @@ Features: ## 0.1.0 (September 26, 2018) * Initial release + From dddf8fa1d3c7bfff78add6a772ace753644de6a6 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 3 Oct 2022 16:10:59 +0000 Subject: [PATCH 155/235] backport of commit 7c33284165ba1613d74e189594c35c07300f4ac3 --- charts/consul/values.yaml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 1489faac75..2378e9aa9a 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -515,6 +515,25 @@ global: # @type: string secretKey: null + # job configures settings for the server-acl-init and server-acl-cleanup jobs + job: + # tolerations configures the taints and tolerations for the server-acl-init + # and server-acl-cleanup jobs. This should be a multi-line string matching the + # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + tolerations: "" + + # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # labels for the server-acl-init and server-acl-cleanup jobs pod assignment, formatted as a multi-line string. + # + # Example: + # + # ```yaml + # nodeSelector: | + # beta.kubernetes.io/arch: amd64 + # ``` + # + # @type: string + nodeSelector: null # [Enterprise Only] This value refers to a Kubernetes or Vault secret that you have created # that contains your enterprise license. It is required if you are using an From d861b36ce744efe90e37120991acf9af41d81c4f Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 3 Oct 2022 16:11:13 +0000 Subject: [PATCH 156/235] backport of commit c42526aa40016f6cf46cd7407645e7c6ee7c8972 --- charts/consul/values.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 2378e9aa9a..fc20ddd27b 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -3084,6 +3084,19 @@ webhookCertManager: # @type: string tolerations: null + # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # labels for webhook cert manager pod assignment, formatted as a multi-line string. + # + # Example: + # + # ```yaml + # nodeSelector: | + # beta.kubernetes.io/arch: amd64 + # ``` + # + # @type: string + nodeSelector: null + # Configures a demo Prometheus installation. prometheus: # When true, the Helm chart will install a demo Prometheus server instance From 8ccb2c379cc83c2d733c703d980a51acc439204b Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 3 Oct 2022 16:40:28 +0000 Subject: [PATCH 157/235] backport of commit 00d934975f53d6608630773e77a5055d152d43ca --- .../webhook-cert-manager-deployment.yaml | 6 ++++- .../unit/webhook-cert-manager-deployment.bats | 23 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/charts/consul/templates/webhook-cert-manager-deployment.yaml b/charts/consul/templates/webhook-cert-manager-deployment.yaml index 609f3314b3..eef13e78b6 100644 --- a/charts/consul/templates/webhook-cert-manager-deployment.yaml +++ b/charts/consul/templates/webhook-cert-manager-deployment.yaml @@ -64,6 +64,10 @@ spec: {{- if .Values.webhookCertManager.tolerations }} tolerations: {{ tpl .Values.webhookCertManager.tolerations . | indent 8 | trim }} - {{- end}} + {{- end }} + {{- if .Values.webhookCertManager.nodeSelector }} + nodeSelector: + {{ tpl .Values.webhookCertManager.nodeSelector . | indent 8 | trim }} + {{- end }} {{- end }} diff --git a/charts/consul/test/unit/webhook-cert-manager-deployment.bats b/charts/consul/test/unit/webhook-cert-manager-deployment.bats index 78b6e52997..71d2e35c3a 100644 --- a/charts/consul/test/unit/webhook-cert-manager-deployment.bats +++ b/charts/consul/test/unit/webhook-cert-manager-deployment.bats @@ -63,6 +63,29 @@ load _helpers [ "${actual}" = "value" ] } +@test "webhookCertManager/Deployment: no nodeSelector by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/webhook-cert-manager-deployment.yaml \ + --set 'controller.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.nodeSelector' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "webhookCertManager/Deployment: nodeSelector can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/webhook-cert-manager-deployment.yaml \ + --set 'controller.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'webhookCertManager.nodeSelector=- key: value' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.nodeSelector[0].key' | tee /dev/stderr) + [ "${actual}" = "value" ] +} + #-------------------------------------------------------------------- # Vault From 59684cde0d68253168ebb57ea12ee183d7ec8890 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 3 Oct 2022 17:14:42 +0000 Subject: [PATCH 158/235] backport of commit b609ab509b1fc098f8f2c8b631bc146cf88575c7 --- .../consul/templates/server-acl-init-job.yaml | 8 ++++ .../consul/test/unit/server-acl-init-job.bats | 45 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index 8709b82af7..0307546c37 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -328,6 +328,14 @@ spec: limits: memory: "50Mi" cpu: "50m" + {{- if .Values.global.acls.job.tolerations }} + tolerations: + {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} + {{- end }} + {{- if .Values.global.acls.job.nodeSelector }} + nodeSelector: + {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/server-acl-init-job.bats b/charts/consul/test/unit/server-acl-init-job.bats index 7b442a2ef8..9fdb96a31d 100644 --- a/charts/consul/test/unit/server-acl-init-job.bats +++ b/charts/consul/test/unit/server-acl-init-job.bats @@ -1551,6 +1551,51 @@ load _helpers [ "${actual}" = "true" ] } +#-------------------------------------------------------------------- +# global.acls.job + +@test "serverACLInit/Job: tolerations not set by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].tolerations' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "serverACLInit/Job: tolerations can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.acls.job.tolerations=- key: value' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].tolerations[0].key' | tee /dev/stderr) + [ "${actual}" = "value" ] +} + +@test "serverACLInit/Job: nodeSelector not set by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].nodeSelector' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "serverACLInit/Job: nodeSelector can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.acls.job.nodeSelector=- key: value' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].nodeSelector[0].key' | tee /dev/stderr) + [ "${actual}" = "value" ] +} + #-------------------------------------------------------------------- # externalServers.enabled From 6eb307a5245634ea224cf7c363e01e43877a1b25 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 3 Oct 2022 17:16:49 +0000 Subject: [PATCH 159/235] backport of commit 928772d8083e0abd868642b59bcf6015647cb355 --- .../server-acl-init-cleanup-job.yaml | 8 ++++ .../unit/server-acl-init-cleanup-job.bats | 45 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/charts/consul/templates/server-acl-init-cleanup-job.yaml b/charts/consul/templates/server-acl-init-cleanup-job.yaml index 4db5e356e3..f2342cf661 100644 --- a/charts/consul/templates/server-acl-init-cleanup-job.yaml +++ b/charts/consul/templates/server-acl-init-cleanup-job.yaml @@ -62,6 +62,14 @@ spec: limits: memory: "50Mi" cpu: "50m" + {{- if .Values.global.acls.job.tolerations }} + tolerations: + {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} + {{- end }} + {{- if .Values.global.acls.job.nodeSelector }} + nodeSelector: + {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/server-acl-init-cleanup-job.bats b/charts/consul/test/unit/server-acl-init-cleanup-job.bats index 3cc17b2682..3fee687e42 100644 --- a/charts/consul/test/unit/server-acl-init-cleanup-job.bats +++ b/charts/consul/test/unit/server-acl-init-cleanup-job.bats @@ -70,3 +70,48 @@ load _helpers yq 'length > 0' | tee /dev/stderr) [ "${actual}" = "true" ] } + +#-------------------------------------------------------------------- +# global.acls.job + +@test "serverACLInitCleanup/Job: tolerations not set by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].tolerations' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "serverACLInitCleanup/Job: tolerations can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.acls.job.tolerations=- key: value' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].tolerations[0].key' | tee /dev/stderr) + [ "${actual}" = "value" ] +} + +@test "serverACLInit/Job: nodeSelector not set by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].nodeSelector' | tee /dev/stderr) + [ "${actual}" = "null" ] +} + +@test "serverACLInit/Job: nodeSelector can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.acls.job.nodeSelector=- key: value' \ + . | tee /dev/stderr | + yq -r '.spec.template.spec.containers[0].nodeSelector[0].key' | tee /dev/stderr) + [ "${actual}" = "value" ] +} From 271249f9eee038927cc0c80e133b992b9e6ab88b Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Mon, 3 Oct 2022 21:16:01 +0000 Subject: [PATCH 160/235] backport of commit 4f9b49c73ba309f27c1c2a6d156f6d761cbe0fe1 --- .../templates/server-acl-init-cleanup-job.yaml | 16 ++++++++-------- charts/consul/templates/server-acl-init-job.yaml | 16 ++++++++-------- .../test/unit/server-acl-init-cleanup-job.bats | 8 ++++---- charts/consul/test/unit/server-acl-init-job.bats | 8 ++++---- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/charts/consul/templates/server-acl-init-cleanup-job.yaml b/charts/consul/templates/server-acl-init-cleanup-job.yaml index f2342cf661..300818988c 100644 --- a/charts/consul/templates/server-acl-init-cleanup-job.yaml +++ b/charts/consul/templates/server-acl-init-cleanup-job.yaml @@ -62,14 +62,14 @@ spec: limits: memory: "50Mi" cpu: "50m" - {{- if .Values.global.acls.job.tolerations }} - tolerations: - {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} - {{- end }} - {{- if .Values.global.acls.job.nodeSelector }} - nodeSelector: - {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} - {{- end }} + {{- if .Values.global.acls.job.tolerations }} + tolerations: + {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} + {{- end }} + {{- if .Values.global.acls.job.nodeSelector }} + nodeSelector: + {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index 0307546c37..a4144ef244 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -328,14 +328,14 @@ spec: limits: memory: "50Mi" cpu: "50m" - {{- if .Values.global.acls.job.tolerations }} - tolerations: - {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} - {{- end }} - {{- if .Values.global.acls.job.nodeSelector }} - nodeSelector: - {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} - {{- end }} + {{- if .Values.global.acls.job.tolerations }} + tolerations: + {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} + {{- end }} + {{- if .Values.global.acls.job.nodeSelector }} + nodeSelector: + {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/server-acl-init-cleanup-job.bats b/charts/consul/test/unit/server-acl-init-cleanup-job.bats index 3fee687e42..0fe599b2e2 100644 --- a/charts/consul/test/unit/server-acl-init-cleanup-job.bats +++ b/charts/consul/test/unit/server-acl-init-cleanup-job.bats @@ -80,7 +80,7 @@ load _helpers -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].tolerations' | tee /dev/stderr) + yq -r '.spec.template.spec.tolerations' | tee /dev/stderr) [ "${actual}" = "null" ] } @@ -91,7 +91,7 @@ load _helpers --set 'global.acls.manageSystemACLs=true' \ --set 'global.acls.job.tolerations=- key: value' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].tolerations[0].key' | tee /dev/stderr) + yq -r '.spec.template.spec.tolerations[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] } @@ -101,7 +101,7 @@ load _helpers -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].nodeSelector' | tee /dev/stderr) + yq -r '.spec.template.spec.nodeSelector' | tee /dev/stderr) [ "${actual}" = "null" ] } @@ -112,6 +112,6 @@ load _helpers --set 'global.acls.manageSystemACLs=true' \ --set 'global.acls.job.nodeSelector=- key: value' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].nodeSelector[0].key' | tee /dev/stderr) + yq -r '.spec.template.spec.nodeSelector[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] } diff --git a/charts/consul/test/unit/server-acl-init-job.bats b/charts/consul/test/unit/server-acl-init-job.bats index 9fdb96a31d..76a4324927 100644 --- a/charts/consul/test/unit/server-acl-init-job.bats +++ b/charts/consul/test/unit/server-acl-init-job.bats @@ -1560,7 +1560,7 @@ load _helpers -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].tolerations' | tee /dev/stderr) + yq -r '.spec.template.spec.tolerations' | tee /dev/stderr) [ "${actual}" = "null" ] } @@ -1571,7 +1571,7 @@ load _helpers --set 'global.acls.manageSystemACLs=true' \ --set 'global.acls.job.tolerations=- key: value' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].tolerations[0].key' | tee /dev/stderr) + yq -r '.spec.template.spec.tolerations[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] } @@ -1581,7 +1581,7 @@ load _helpers -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].nodeSelector' | tee /dev/stderr) + yq -r '.spec.template.spec.nodeSelector' | tee /dev/stderr) [ "${actual}" = "null" ] } @@ -1592,7 +1592,7 @@ load _helpers --set 'global.acls.manageSystemACLs=true' \ --set 'global.acls.job.nodeSelector=- key: value' \ . | tee /dev/stderr | - yq -r '.spec.template.spec.containers[0].nodeSelector[0].key' | tee /dev/stderr) + yq -r '.spec.template.spec.nodeSelector[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] } From 5911a6f19bced014f55be6c064c0d2965bb9ed87 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Fri, 14 Oct 2022 19:09:18 +0000 Subject: [PATCH 161/235] backport of commit e5a5a6f53f6a625027e1b6b37bad4b28bfda2b22 --- .../server-acl-init-cleanup-job.yaml | 8 ++--- .../consul/templates/server-acl-init-job.yaml | 8 ++--- .../unit/server-acl-init-cleanup-job.bats | 6 ++-- .../consul/test/unit/server-acl-init-job.bats | 6 ++-- charts/consul/values.yaml | 36 +++++++++---------- 5 files changed, 31 insertions(+), 33 deletions(-) diff --git a/charts/consul/templates/server-acl-init-cleanup-job.yaml b/charts/consul/templates/server-acl-init-cleanup-job.yaml index 300818988c..eb38eab090 100644 --- a/charts/consul/templates/server-acl-init-cleanup-job.yaml +++ b/charts/consul/templates/server-acl-init-cleanup-job.yaml @@ -62,13 +62,13 @@ spec: limits: memory: "50Mi" cpu: "50m" - {{- if .Values.global.acls.job.tolerations }} + {{- if .Values.global.acls.tolerations }} tolerations: - {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} + {{ tpl .Values.global.acls.tolerations . | indent 12 | trim }} {{- end }} - {{- if .Values.global.acls.job.nodeSelector }} + {{- if .Values.global.acls.nodeSelector }} nodeSelector: - {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} + {{ tpl .Values.global.acls.nodeSelector . | indent 12 | trim }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index a4144ef244..2ea4b3bcb7 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -328,13 +328,13 @@ spec: limits: memory: "50Mi" cpu: "50m" - {{- if .Values.global.acls.job.tolerations }} + {{- if .Values.global.acls.tolerations }} tolerations: - {{ tpl .Values.global.acls.job.tolerations . | indent 12 | trim }} + {{ tpl .Values.global.acls.tolerations . | indent 12 | trim }} {{- end }} - {{- if .Values.global.acls.job.nodeSelector }} + {{- if .Values.global.acls.nodeSelector }} nodeSelector: - {{ tpl .Values.global.acls.job.nodeSelector . | indent 12 | trim }} + {{ tpl .Values.global.acls.nodeSelector . | indent 12 | trim }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/server-acl-init-cleanup-job.bats b/charts/consul/test/unit/server-acl-init-cleanup-job.bats index 0fe599b2e2..3005b2856a 100644 --- a/charts/consul/test/unit/server-acl-init-cleanup-job.bats +++ b/charts/consul/test/unit/server-acl-init-cleanup-job.bats @@ -72,7 +72,7 @@ load _helpers } #-------------------------------------------------------------------- -# global.acls.job +# global.acls.tolerations and global.acls.nodeSelector @test "serverACLInitCleanup/Job: tolerations not set by default" { cd `chart_dir` @@ -89,7 +89,7 @@ load _helpers local actual=$(helm template \ -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ - --set 'global.acls.job.tolerations=- key: value' \ + --set 'global.acls.tolerations=- key: value' \ . | tee /dev/stderr | yq -r '.spec.template.spec.tolerations[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] @@ -110,7 +110,7 @@ load _helpers local actual=$(helm template \ -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ - --set 'global.acls.job.nodeSelector=- key: value' \ + --set 'global.acls.nodeSelector=- key: value' \ . | tee /dev/stderr | yq -r '.spec.template.spec.nodeSelector[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] diff --git a/charts/consul/test/unit/server-acl-init-job.bats b/charts/consul/test/unit/server-acl-init-job.bats index 76a4324927..cc9bfb5f77 100644 --- a/charts/consul/test/unit/server-acl-init-job.bats +++ b/charts/consul/test/unit/server-acl-init-job.bats @@ -1552,7 +1552,7 @@ load _helpers } #-------------------------------------------------------------------- -# global.acls.job +# global.acls.tolerations and global.acls.nodeSelector @test "serverACLInit/Job: tolerations not set by default" { cd `chart_dir` @@ -1569,7 +1569,7 @@ load _helpers local actual=$(helm template \ -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ - --set 'global.acls.job.tolerations=- key: value' \ + --set 'global.acls.tolerations=- key: value' \ . | tee /dev/stderr | yq -r '.spec.template.spec.tolerations[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] @@ -1590,7 +1590,7 @@ load _helpers local actual=$(helm template \ -s templates/server-acl-init-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ - --set 'global.acls.job.nodeSelector=- key: value' \ + --set 'global.acls.nodeSelector=- key: value' \ . | tee /dev/stderr | yq -r '.spec.template.spec.nodeSelector[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index fc20ddd27b..714ececeb4 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -515,25 +515,23 @@ global: # @type: string secretKey: null - # job configures settings for the server-acl-init and server-acl-cleanup jobs - job: - # tolerations configures the taints and tolerations for the server-acl-init - # and server-acl-cleanup jobs. This should be a multi-line string matching the - # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. - tolerations: "" - - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) - # labels for the server-acl-init and server-acl-cleanup jobs pod assignment, formatted as a multi-line string. - # - # Example: - # - # ```yaml - # nodeSelector: | - # beta.kubernetes.io/arch: amd64 - # ``` - # - # @type: string - nodeSelector: null + # tolerations configures the taints and tolerations for the server-acl-init + # and server-acl-cleanup jobs. This should be a multi-line string matching the + # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + tolerations: "" + + # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # labels for the server-acl-init and server-acl-cleanup jobs pod assignment, formatted as a multi-line string. + # + # Example: + # + # ```yaml + # nodeSelector: | + # beta.kubernetes.io/arch: amd64 + # ``` + # + # @type: string + nodeSelector: null # [Enterprise Only] This value refers to a Kubernetes or Vault secret that you have created # that contains your enterprise license. It is required if you are using an From 5cb0b6692bf43cc8662d23fc82d38199048d52b5 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Fri, 14 Oct 2022 22:32:13 +0000 Subject: [PATCH 162/235] backport of commit 19012ef954126b0fea69aad6b432959ed9679c83 --- charts/consul/test/unit/server-acl-init-cleanup-job.bats | 4 ++-- charts/consul/values.yaml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/charts/consul/test/unit/server-acl-init-cleanup-job.bats b/charts/consul/test/unit/server-acl-init-cleanup-job.bats index 3005b2856a..1c285c8f4d 100644 --- a/charts/consul/test/unit/server-acl-init-cleanup-job.bats +++ b/charts/consul/test/unit/server-acl-init-cleanup-job.bats @@ -95,7 +95,7 @@ load _helpers [ "${actual}" = "value" ] } -@test "serverACLInit/Job: nodeSelector not set by default" { +@test "serverACLInitCleanup/Job: nodeSelector not set by default" { cd `chart_dir` local actual=$(helm template \ -s templates/server-acl-init-job.yaml \ @@ -105,7 +105,7 @@ load _helpers [ "${actual}" = "null" ] } -@test "serverACLInit/Job: nodeSelector can be set" { +@test "serverACLInitCleanup/Job: nodeSelector can be set" { cd `chart_dir` local actual=$(helm template \ -s templates/server-acl-init-job.yaml \ diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 714ececeb4..52ba1e25cd 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -516,12 +516,12 @@ global: secretKey: null # tolerations configures the taints and tolerations for the server-acl-init - # and server-acl-cleanup jobs. This should be a multi-line string matching the + # and server-acl-init-cleanup jobs. This should be a multi-line string matching the # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. tolerations: "" # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) - # labels for the server-acl-init and server-acl-cleanup jobs pod assignment, formatted as a multi-line string. + # labels for the server-acl-init and server-acl-init-cleanup jobs pod assignment, formatted as a multi-line string. # # Example: # @@ -3083,7 +3083,7 @@ webhookCertManager: tolerations: null # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) - # labels for webhook cert manager pod assignment, formatted as a multi-line string. + # labels for the webhook-cert-manager pod assignment, formatted as a multi-line string. # # Example: # From 80677f12445efe3a36ae60740926019c2e1c3205 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Fri, 14 Oct 2022 22:34:20 +0000 Subject: [PATCH 163/235] backport of commit 24e616ce32b8f1f33a3c72c39fb29fbb2c621c79 --- charts/consul/templates/server-acl-init-job.yaml | 4 ++-- charts/consul/test/unit/server-acl-init-cleanup-job.bats | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index 2ea4b3bcb7..b2f770db7a 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -330,11 +330,11 @@ spec: cpu: "50m" {{- if .Values.global.acls.tolerations }} tolerations: - {{ tpl .Values.global.acls.tolerations . | indent 12 | trim }} + {{ tpl .Values.global.acls.tolerations . | indent 8 | trim }} {{- end }} {{- if .Values.global.acls.nodeSelector }} nodeSelector: - {{ tpl .Values.global.acls.nodeSelector . | indent 12 | trim }} + {{ tpl .Values.global.acls.nodeSelector . | indent 8 | trim }} {{- end }} {{- end }} {{- end }} diff --git a/charts/consul/test/unit/server-acl-init-cleanup-job.bats b/charts/consul/test/unit/server-acl-init-cleanup-job.bats index 1c285c8f4d..cb57374116 100644 --- a/charts/consul/test/unit/server-acl-init-cleanup-job.bats +++ b/charts/consul/test/unit/server-acl-init-cleanup-job.bats @@ -77,7 +77,7 @@ load _helpers @test "serverACLInitCleanup/Job: tolerations not set by default" { cd `chart_dir` local actual=$(helm template \ - -s templates/server-acl-init-job.yaml \ + -s templates/server-acl-init-cleanup-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | yq -r '.spec.template.spec.tolerations' | tee /dev/stderr) @@ -87,7 +87,7 @@ load _helpers @test "serverACLInitCleanup/Job: tolerations can be set" { cd `chart_dir` local actual=$(helm template \ - -s templates/server-acl-init-job.yaml \ + -s templates/server-acl-init-cleanup-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ --set 'global.acls.tolerations=- key: value' \ . | tee /dev/stderr | @@ -98,7 +98,7 @@ load _helpers @test "serverACLInitCleanup/Job: nodeSelector not set by default" { cd `chart_dir` local actual=$(helm template \ - -s templates/server-acl-init-job.yaml \ + -s templates/server-acl-init-cleanup-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ . | tee /dev/stderr | yq -r '.spec.template.spec.nodeSelector' | tee /dev/stderr) @@ -108,7 +108,7 @@ load _helpers @test "serverACLInitCleanup/Job: nodeSelector can be set" { cd `chart_dir` local actual=$(helm template \ - -s templates/server-acl-init-job.yaml \ + -s templates/server-acl-init-cleanup-job.yaml \ --set 'global.acls.manageSystemACLs=true' \ --set 'global.acls.nodeSelector=- key: value' \ . | tee /dev/stderr | From 8e2b080c829f5fdac808923d8d825dfa8fd33bba Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Sat, 15 Oct 2022 00:37:40 +0000 Subject: [PATCH 164/235] backport of commit 9a3ddc4e2358e0658d1323e6395b4d00b3bb20e0 --- charts/consul/templates/server-acl-init-cleanup-job.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/charts/consul/templates/server-acl-init-cleanup-job.yaml b/charts/consul/templates/server-acl-init-cleanup-job.yaml index eb38eab090..697427ab5f 100644 --- a/charts/consul/templates/server-acl-init-cleanup-job.yaml +++ b/charts/consul/templates/server-acl-init-cleanup-job.yaml @@ -64,11 +64,11 @@ spec: cpu: "50m" {{- if .Values.global.acls.tolerations }} tolerations: - {{ tpl .Values.global.acls.tolerations . | indent 12 | trim }} + {{ tpl .Values.global.acls.tolerations . | indent 8 | trim }} {{- end }} {{- if .Values.global.acls.nodeSelector }} nodeSelector: - {{ tpl .Values.global.acls.nodeSelector . | indent 12 | trim }} + {{ tpl .Values.global.acls.nodeSelector . | indent 8 | trim }} {{- end }} {{- end }} {{- end }} From 23d0af1f552c1b6b007162c70b0aff3bc76ceb77 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Tue, 18 Oct 2022 22:14:55 +0000 Subject: [PATCH 165/235] backport of commit bccf760f5eac93b7b8b50641a7de2d5582667a90 --- charts/consul/values.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 52ba1e25cd..1cbd709576 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -2969,8 +2969,9 @@ apiGateway: # Example: # # ```yaml - # service: | - # - external-dns.alpha.kubernetes.io/hostname + # service: + # annotations: | + # - external-dns.alpha.kubernetes.io/hostname # ``` # # @type: string From f08a70beb1e99828baf7562b6bae6b483f7b2c2f Mon Sep 17 00:00:00 2001 From: Michele Degges Date: Wed, 19 Oct 2022 17:51:47 +0000 Subject: [PATCH 166/235] backport of commit 428b3afaa07b56021688d36372dfc50298c20b0a --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 217741fa8a..18b26f99fa 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -292,7 +292,7 @@ jobs: pkg_name: consul-k8s-control-plane_${{ env.version }} bin_name: consul-k8s-control-plane workdir: control-plane - redhat_tag: scan.connect.redhat.com/ospid-611ca2f89a9b407267837100/consul-k8s-control-plane:${{env.version}}-ubi + redhat_tag: quay.io/redhat-isv-containers/611ca2f89a9b407267837100/consul-k8s-control-plane:${{env.version}}-ubi build-docker-ubi-dockerhub: name: Docker ${{ matrix.arch }} UBI build for DockerHub From 2391dd2ea064db1c583b88b552d87073e45b726f Mon Sep 17 00:00:00 2001 From: Sam Salisbury Date: Thu, 20 Oct 2022 15:01:24 +0000 Subject: [PATCH 167/235] backport of commit 4ed72faf6d9e2ebf58056e0a2933e9cdbf9139d9 --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 18b26f99fa..c6b107e141 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -292,7 +292,7 @@ jobs: pkg_name: consul-k8s-control-plane_${{ env.version }} bin_name: consul-k8s-control-plane workdir: control-plane - redhat_tag: quay.io/redhat-isv-containers/611ca2f89a9b407267837100/consul-k8s-control-plane:${{env.version}}-ubi + redhat_tag: quay.io/redhat-isv-containers/611ca2f89a9b407267837100:${{env.version}}-ubi build-docker-ubi-dockerhub: name: Docker ${{ matrix.arch }} UBI build for DockerHub From ef1ca6f6d640b0b612706786d61048d546bd6e14 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Fri, 21 Oct 2022 18:35:54 -0400 Subject: [PATCH 168/235] Add CHANGELOG entry for PR 1581 (#1627) (#1630) --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d292b2306b..7c9a83c026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## UNRELEASED + +IMPROVEMENTS: +* Helm: + * Add `tolerations` and `nodeSelector` to Server ACL init jobs and `nodeSelector` to Webhook cert manager. [[GH-1581](https://github.com/hashicorp/consul-k8s/pull/1581)] + ## 0.49.0 (September 30, 2022) FEATURES: From e8f2490d8139326f5ce44407b9718d562163416a Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Tue, 25 Oct 2022 11:24:24 -0700 Subject: [PATCH 169/235] Mw/cherry pick ac updates (#1649) * removed make target for GitHub, no longer needed * The name CLI conflicts with the runner - build consul-k8s CLI in pipeline instead for GH action (in future commit) - build consul-K8s CLI in pipeline for CircleCI. CircleCI uses some different go pathing so can't use make cli-dev explicitly for build-cli step - change name of cli binary from cli to consul-k8s * replace special characters in tests - GitHub actions can't upload test files with special characters in the name, so replace all special characters with underscores (_) --- .circleci/config.yml | 19 +++++++++++++++++-- acceptance/framework/cli/cli.go | 15 +++++++-------- acceptance/framework/config/config.go | 1 - acceptance/framework/k8s/debug.go | 11 +++++++++-- control-plane/Makefile | 20 -------------------- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3196ac2e50..d57c6f86d3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -27,7 +27,7 @@ commands: install-prereqs: steps: - run: - name: Install gotestsum, kind, kubectl, and helm + name: Install go, gotestsum, kind, kubectl, and helm command: | wget https://golang.org/dl/go1.18.3.linux-amd64.tar.gz sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz @@ -71,6 +71,16 @@ commands: make kind-cni-calico kind create cluster --config=acceptance/framework/environment/cni-kind/kind.config --name dc2 --image kindest/node:<< parameters.version >> make kind-cni-calico + build-cli: + steps: + - run: + name: Build consul-k8s CLI + working_directory: *cli-path + command: | + go build -o ./bin/consul-k8s + sudo cp ./bin/consul-k8s /usr/local/go/bin/ + consul-k8s version + run-acceptance-tests: parameters: failfast: @@ -518,6 +528,7 @@ jobs: key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} paths: - ~/.go_workspace/pkg/mod + - build-cli - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: failfast: true @@ -550,6 +561,7 @@ jobs: key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} paths: - ~/.go_workspace/pkg/mod + - build-cli - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: failfast: true @@ -582,6 +594,7 @@ jobs: key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} paths: - ~/.go_workspace/pkg/mod + - build-cli - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: failfast: true @@ -1108,6 +1121,7 @@ jobs: key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} paths: - ~/.go_workspace/pkg/mod + - build-cli - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION @@ -1184,6 +1198,7 @@ jobs: key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} paths: - ~/.go_workspace/pkg/mod + - build-cli - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.13" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION @@ -1204,6 +1219,7 @@ workflows: # The rest of these CircleCI jobs have been migrated to Github Actions. We need to wait until # the summer of 2022 for larger puplic Github Action VMs be available before the acceptance tests can # be moved + # Run acceptance tests using the docker image built for the control plane - build-distro: OS: "linux" ARCH: "amd64 arm64" @@ -1212,7 +1228,6 @@ workflows: context: consul-ci requires: - build-distros-linux - # Run acceptance tests using the docker image built for the control plane - acceptance: context: consul-ci requires: diff --git a/acceptance/framework/cli/cli.go b/acceptance/framework/cli/cli.go index 81fe353525..5297382d94 100644 --- a/acceptance/framework/cli/cli.go +++ b/acceptance/framework/cli/cli.go @@ -7,22 +7,21 @@ import ( "testing" "github.com/gruntwork-io/terratest/modules/k8s" - "github.com/hashicorp/consul-k8s/acceptance/framework/config" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" ) +const ( + cliBinaryName = "consul-k8s" +) + // CLI provides access to compile and execute commands with the `consul-k8s` CLI. type CLI struct { initialized bool } -// NewCLI compiles the `consul-k8s` CLI and returns a handle to execute commands -// with the binary. +// NewCLI returns a handle to execute commands with the consul-k8s binary. func NewCLI() (*CLI, error) { - cmd := exec.Command("go", "install", ".") - cmd.Dir = config.CLIPath - _, err := cmd.Output() - return &CLI{true}, err + return &CLI{true}, nil } // Run runs the CLI with the given args. @@ -40,6 +39,6 @@ func (c *CLI) Run(t *testing.T, options *k8s.KubectlOptions, args ...string) ([] } logger.Logf(t, "Running `consul-k8s %s`", strings.Join(args, " ")) - cmd := exec.Command("cli", args...) + cmd := exec.Command(cliBinaryName, args...) return cmd.Output() } diff --git a/acceptance/framework/config/config.go b/acceptance/framework/config/config.go index f0b50358fe..11a04f1622 100644 --- a/acceptance/framework/config/config.go +++ b/acceptance/framework/config/config.go @@ -15,7 +15,6 @@ import ( // Note: this will need to be changed if this file is moved. const ( HelmChartPath = "../../../charts/consul" - CLIPath = "../../../cli" LicenseSecretName = "license" LicenseSecretKey = "key" ) diff --git a/acceptance/framework/k8s/debug.go b/acceptance/framework/k8s/debug.go index 338c6ce995..c1f0c5d7d6 100644 --- a/acceptance/framework/k8s/debug.go +++ b/acceptance/framework/k8s/debug.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path/filepath" + "regexp" "testing" "github.com/gruntwork-io/terratest/modules/k8s" @@ -26,8 +27,14 @@ func WritePodsDebugInfoIfFailed(t *testing.T, kubectlOptions *k8s.KubectlOptions contextName := environment.KubernetesContextFromOptions(t, kubectlOptions) - // Create a directory for the test. - testDebugDirectory := filepath.Join(debugDirectory, t.Name(), contextName) + // Create a directory for the test, first remove special characters from test name + reg, err := regexp.Compile("[^A-Za-z0-9/_-]+") + if err != nil { + logger.Log(t, "unable to generate regex for test name special character replacement", "err", err) + } + tn := reg.ReplaceAllString(t.Name(), "_") + + testDebugDirectory := filepath.Join(debugDirectory, tn, contextName) require.NoError(t, os.MkdirAll(testDebugDirectory, 0755)) logger.Logf(t, "dumping logs, pod info, and envoy config for %s to %s", labelSelector, testDebugDirectory) diff --git a/control-plane/Makefile b/control-plane/Makefile index 7dd5ef80d3..4c3cbac971 100644 --- a/control-plane/Makefile +++ b/control-plane/Makefile @@ -51,24 +51,4 @@ ifeq ($(CIRCLE_BRANCH), main) @echo "Pushed dev image to: $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest" endif -# In Github Actions, the linux binary will be attached from a previous step at pkg/bin/linux_amd64/. This make target -# should only run in CI and not locally. -ci.dev-docker-github: - @echo "Pulling consul-k8s container image - $(CONSUL_K8S_IMAGE_VERSION)" - @docker pull hashicorp/consul-k8s:$(CONSUL_K8S_IMAGE_VERSION) >/dev/null #todo change this back after pulling it the first time since the dockerfile is FROM this image - @echo "Building consul-k8s Development container - $(CI_DEV_DOCKER_IMAGE_NAME)" - @docker build -t '$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT)' \ - --build-arg CONSUL_K8S_IMAGE_VERSION=$(CONSUL_K8S_IMAGE_VERSION) \ - --label COMMIT_SHA=$(GITHUB_SHA) \ - --label PULL_REQUEST=$(GITHIB_PULL_REQUEST) \ - --label GITHUB_BUILD_URL=$(GITHUB_SERVER_URL)/$(GITHUB_REPOSITORY)/actions/runs/$(GITHUB_RUN_ID) \ - $(CI_DEV_DOCKER_WORKDIR) -f $(CURDIR)/build-support/docker/Dev.dockerfile - @echo $(DOCKER_PASS) | docker login -u="$(DOCKER_USER)" --password-stdin - @echo "Pushing dev image to: https://cloud.docker.com/u/$(CI_DEV_DOCKER_NAMESPACE)/repository/docker/$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME)" - @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) -ifeq ($(GITHUB_REF_NAME), main) - @docker tag $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):$(GIT_COMMIT) $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest - @docker push $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_DOCKER_IMAGE_NAME):latest -endif - .PHONY: ci.dev-tree ci.dev-docker ci.dev-docker-github From fd963adbc9e4b956fd1b6a655c7e91e4cfecffe7 Mon Sep 17 00:00:00 2001 From: Nathan Coleman Date: Thu, 27 Oct 2022 14:28:27 -0400 Subject: [PATCH 170/235] api-gateway: Allow controller to read MeshService resource (#1574) (#1653) * Allow the API gateway controller to read MeshService resource * Add changelog entry Co-authored-by: Mike Morris Co-authored-by: Mike Morris --- CHANGELOG.md | 1 + .../templates/api-gateway-controller-clusterrole.yaml | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c9a83c026..77c28ed475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ IMPROVEMENTS: * Helm: * Add `tolerations` and `nodeSelector` to Server ACL init jobs and `nodeSelector` to Webhook cert manager. [[GH-1581](https://github.com/hashicorp/consul-k8s/pull/1581)] + * API Gateway: Allow controller to read MeshServices for use as a route backend. [[GH-1574](https://github.com/hashicorp/consul-k8s/pull/1574)] ## 0.49.0 (September 30, 2022) diff --git a/charts/consul/templates/api-gateway-controller-clusterrole.yaml b/charts/consul/templates/api-gateway-controller-clusterrole.yaml index cce6b5b6c6..0676c6ae4e 100644 --- a/charts/consul/templates/api-gateway-controller-clusterrole.yaml +++ b/charts/consul/templates/api-gateway-controller-clusterrole.yaml @@ -26,6 +26,14 @@ rules: - gatewayclassconfigs/finalizers verbs: - update +- apiGroups: + - api-gateway.consul.hashicorp.com + resources: + - meshservices + verbs: + - get + - list + - watch - apiGroups: - apps resources: From 70145c9c9b3b6d4341216acafbe4eaf86c0fad55 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Tue, 1 Nov 2022 07:13:26 +0000 Subject: [PATCH 171/235] backport of commit f67364b13711aa22d380f508b9f01074c12aed9d --- .circleci/config.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d57c6f86d3..e4d91332f4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -685,6 +685,7 @@ jobs: - checkout + - build-cli - run: name: terraform init & apply working_directory: *gke-terraform-path @@ -753,6 +754,7 @@ jobs: - checkout + - build-cli - run: name: terraform init & apply working_directory: *gke-terraform-path @@ -813,6 +815,7 @@ jobs: steps: - checkout + - build-cli - run: name: terraform init & apply working_directory: *aks-terraform-path @@ -870,6 +873,7 @@ jobs: steps: - checkout + - build-cli - run: name: terraform init & apply working_directory: *aks-terraform-path @@ -926,6 +930,7 @@ jobs: steps: - checkout + - build-cli - run: name: configure aws command: | @@ -989,6 +994,7 @@ jobs: steps: - checkout + - build-cli - run: name: configure aws command: | @@ -1051,6 +1057,7 @@ jobs: steps: - checkout + - build-cli - run: name: terraform init & apply working_directory: *openshift-terraform-path From 9aefaa23ebed949b58d691f566814b75163ce603 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Thu, 3 Nov 2022 08:09:26 -0700 Subject: [PATCH 172/235] Add PodSecurityPolicy for Consul API Gateway controller (#1656) (#1666) * Add PodSecurityPolicy for Consul API Gateway controller * Grant Consul API Gateway controller access to new PodSecurityPolicy * Add unit test coverage for clusterrole + podsecuritypolicy * Add changelog entry * Use YQ@3 friendly select Co-authored-by: Nathan Coleman --- CHANGELOG.md | 1 + .../api-gateway-controller-clusterrole.yaml | 8 ++++ ...-gateway-controller-podsecuritypolicy.yaml | 40 +++++++++++++++++++ .../api-gateway-controller-clusterrole.bats | 12 ++++++ ...-gateway-controller-podsecuritypolicy.bats | 22 ++++++++++ 5 files changed, 83 insertions(+) create mode 100644 charts/consul/templates/api-gateway-controller-podsecuritypolicy.yaml create mode 100644 charts/consul/test/unit/api-gateway-controller-podsecuritypolicy.bats diff --git a/CHANGELOG.md b/CHANGELOG.md index 77c28ed475..c225748fbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ IMPROVEMENTS: * Helm: * Add `tolerations` and `nodeSelector` to Server ACL init jobs and `nodeSelector` to Webhook cert manager. [[GH-1581](https://github.com/hashicorp/consul-k8s/pull/1581)] * API Gateway: Allow controller to read MeshServices for use as a route backend. [[GH-1574](https://github.com/hashicorp/consul-k8s/pull/1574)] + * API Gateway: Create PodSecurityPolicy for controller when `global.enablePodSecurityPolicies=true`. [[GH-1656](https://github.com/hashicorp/consul-k8s/pull/1656)] ## 0.49.0 (September 30, 2022) diff --git a/charts/consul/templates/api-gateway-controller-clusterrole.yaml b/charts/consul/templates/api-gateway-controller-clusterrole.yaml index 0676c6ae4e..f84c5561c2 100644 --- a/charts/consul/templates/api-gateway-controller-clusterrole.yaml +++ b/charts/consul/templates/api-gateway-controller-clusterrole.yaml @@ -244,4 +244,12 @@ rules: - get - patch - update +{{- if .Values.global.enablePodSecurityPolicies }} +- apiGroups: ["policy"] + resources: ["podsecuritypolicies"] + resourceNames: + - {{ template "consul.fullname" . }}-api-gateway-controller + verbs: + - use +{{- end }} {{- end }} diff --git a/charts/consul/templates/api-gateway-controller-podsecuritypolicy.yaml b/charts/consul/templates/api-gateway-controller-podsecuritypolicy.yaml new file mode 100644 index 0000000000..390d084303 --- /dev/null +++ b/charts/consul/templates/api-gateway-controller-podsecuritypolicy.yaml @@ -0,0 +1,40 @@ +{{- if and .Values.apiGateway.enabled .Values.global.enablePodSecurityPolicies }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "consul.fullname" . }}-api-gateway-controller + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: api-gateway-controller +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + # This is redundant with non-root + disallow privilege escalation, + # but we can provide it for defense in depth. + requiredDropCapabilities: + - ALL + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + hostNetwork: false + hostIPC: false + hostPID: false + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: true +{{- end }} diff --git a/charts/consul/test/unit/api-gateway-controller-clusterrole.bats b/charts/consul/test/unit/api-gateway-controller-clusterrole.bats index a3edec027d..b69b6ac966 100644 --- a/charts/consul/test/unit/api-gateway-controller-clusterrole.bats +++ b/charts/consul/test/unit/api-gateway-controller-clusterrole.bats @@ -19,3 +19,15 @@ load _helpers yq 'length > 0' | tee /dev/stderr) [ "${actual}" = "true" ] } + +@test "apiGateway/ClusterRole: uses PodSecurityPolicy with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-clusterrole.yaml \ + --set 'global.enablePodSecurityPolicies=true' \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=foo' \ + . | tee /dev/stderr | + yq '.rules[] | select((.resourceNames[0] == "release-name-consul-api-gateway-controller") and (.resources[0] == "podsecuritypolicies")) | length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} diff --git a/charts/consul/test/unit/api-gateway-controller-podsecuritypolicy.bats b/charts/consul/test/unit/api-gateway-controller-podsecuritypolicy.bats new file mode 100644 index 0000000000..dfd40c793f --- /dev/null +++ b/charts/consul/test/unit/api-gateway-controller-podsecuritypolicy.bats @@ -0,0 +1,22 @@ +#!/usr/bin/env bats + +load _helpers + +@test "apiGateway/PodSecurityPolicy: disabled by default" { + cd `chart_dir` + assert_empty helm template \ + -s templates/api-gateway-controller-podsecuritypolicy.yaml \ + . +} + +@test "apiGateway/PodSecurityPolicy: enabled with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-podsecuritypolicy.yaml \ + --set 'global.enablePodSecurityPolicies=true' \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=foo' \ + . | tee /dev/stderr | + yq 'length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} From 5e75dd8e79852ceb15d5014c6f5b16b43ee2cdce Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Thu, 3 Nov 2022 15:41:22 -0700 Subject: [PATCH 173/235] backport acceptance test pipeline changes for stable releases (#1677) Co-authored-by: Michael Wilkerson --- .circleci/config.yml | 236 ++++++++++++++++++++++++++++++++----------- CONTRIBUTING.md | 3 + 2 files changed, 182 insertions(+), 57 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index e4d91332f4..8bf43c4378 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,13 @@ gke-terraform-path: &gke-terraform-path charts/consul/test/terraform/gke eks-terraform-path: &eks-terraform-path charts/consul/test/terraform/eks aks-terraform-path: &aks-terraform-path charts/consul/test/terraform/aks openshift-terraform-path: &openshift-terraform-path charts/consul/test/terraform/openshift +# This image is built from test/docker/Test.dockerfile +consul-helm-test-image: &consul-helm-test-image docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 +######################## +# COMMANDS +######################## +# Commands define a sequence of steps as a map to be executed and reused in jobs commands: install-prereqs: steps: @@ -49,6 +55,48 @@ commands: wget https://get.helm.sh/helm-v3.7.0-linux-amd64.tar.gz tar -zxvf helm-v3.7.0-linux-amd64.tar.gz sudo mv linux-amd64/helm /usr/local/bin/helm + custom-checkout: + description: | + custom-checkout will perform a custom checkout procedure if provided with an alternative git reference, + otherwise it will run the CircleCI defined checkout command. This is needed as the CircleCI defined checkout + command does not support subsequent git actions after being called. + parameters: + git-ref: + type: string + default: "" + steps: + - when: + condition: << parameters.git-ref >> + steps: + - run: + name: Checkout code + command: | + ssh-keyscan github.com >> ~/.ssh/known_hosts + if [ -e '/home/circleci/project/.git' ] ; then + echo 'Fetching into existing repository' + existing_repo='true' + cd '/home/circleci/project' + git remote set-url origin "$CIRCLE_REPOSITORY_URL" || true + else + echo 'Cloning git repository' + existing_repo='false' + mkdir -p '/home/circleci/project' + cd '/home/circleci/project' + git clone --no-checkout "$CIRCLE_REPOSITORY_URL" . + fi + + if [ "$existing_repo" = 'true' ] || [ 'false' = 'true' ]; then + echo 'Fetching from remote repository' + git fetch --force origin + git fetch --force --tags origin + fi + + echo 'Checking out branch/tag' + git checkout --force "<< parameters.git-ref >>" + - unless: + condition: << parameters.git-ref >> + steps: + - checkout create-kind-clusters: parameters: version: @@ -82,6 +130,9 @@ commands: consul-k8s version run-acceptance-tests: + description: | + Runs the Kind acceptance tests using a provided consul-k8s image, or else attempts to use the image referenced by the + branch name and git reference of the current git commit parameters: failfast: type: boolean @@ -156,6 +207,11 @@ commands: -debug-directory="$TEST_RESULTS/debug" \ -consul-k8s-image=<< parameters.consul-k8s-image >> +######################## +# JOBS +######################## +# Jobs are a collection of steps. These are used in the workflows to define +# what gets run in the pipeline jobs: go-fmt-and-vet-control-plane: executor: go @@ -279,7 +335,6 @@ jobs: GOXPARALLEL: 2 # CircleCI containers are 2 CPU x 4GB RAM steps: - checkout - # Restore go module cache if there is one - restore_cache: keys: @@ -495,7 +550,7 @@ jobs: unit-test-helm-templates: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout @@ -505,6 +560,9 @@ jobs: working_directory: charts/consul command: bats --jobs 4 ./test/unit + ########################### + # KIND ACCEPTANCE TEST JOBS + ########################### acceptance: environment: - TEST_RESULTS: /tmp/test-results @@ -532,7 +590,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: failfast: true - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results - store_artifacts: @@ -565,7 +623,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: failfast: true - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results - store_artifacts: @@ -598,18 +656,18 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: failfast: true - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -enable-cni + additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results - store_artifacts: path: /tmp/test-results - ########################## - # CLEANUP CLOUD RESOURCES - ########################## + ############################## + # CLEANUP CLOUD RESOURCES JOBS + ############################## cleanup-gcp-resources: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - run: name: cleanup leftover resources @@ -627,7 +685,7 @@ jobs: cleanup-azure-resources: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - run: name: cleanup leftover resources @@ -645,7 +703,7 @@ jobs: cleanup-eks-resources: docker: - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout - run: @@ -663,16 +721,15 @@ jobs: fail_only: true failure_message: "EKS cleanup failed" - ######################## - # ACCEPTANCE TESTS - ######################## + ############################# + # CLOUD ACCEPTANCE TEST JOBS + ############################# acceptance-gke-1-23: parallelism: 2 environment: - TEST_RESULTS: /tmp/test-results docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - run: @@ -716,7 +773,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -740,8 +797,7 @@ jobs: environment: - TEST_RESULTS: /tmp/test-results docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - run: @@ -785,7 +841,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -use-gke -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy -enable-cni + additional-flags: -use-gke -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -809,8 +865,7 @@ jobs: environment: - TEST_RESULTS: /tmp/test-results docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout @@ -843,7 +898,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -867,8 +922,7 @@ jobs: environment: - TEST_RESULTS: /tmp/test-results docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout @@ -901,7 +955,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -924,8 +978,7 @@ jobs: environment: - TEST_RESULTS: /tmp/test-results docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout @@ -964,7 +1017,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -988,8 +1041,7 @@ jobs: environment: - TEST_RESULTS: /tmp/test-results docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout @@ -1028,7 +1080,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -1052,8 +1104,7 @@ jobs: TEST_RESULTS: /tmp/test-results parallelism: 1 docker: - # This image is built from test/docker/Test.dockerfile - - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 + - image: *consul-helm-test-image steps: - checkout @@ -1083,7 +1134,7 @@ jobs: - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-openshift -enable-transparent-proxy + additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-openshift -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - store_test_results: path: /tmp/test-results @@ -1102,7 +1153,7 @@ jobs: fail_only: true failure_message: "OpenShift acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-kind-1-23-consul-nightly-1-11: + acceptance-kind-1-23-consul-compat-nightly-1-11: environment: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.11-dev" @@ -1141,7 +1192,7 @@ jobs: fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.11 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-kind-1-23-consul-nightly-1-12: + acceptance-kind-1-23-consul-compat-nightly-1-12: environment: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.12-dev" @@ -1167,6 +1218,7 @@ jobs: key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} paths: - ~/.go_workspace/pkg/mod + - build-cli - run: mkdir -p $TEST_RESULTS - run-acceptance-tests: additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION @@ -1179,7 +1231,7 @@ jobs: fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.12 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" - acceptance-kind-1-23-consul-nightly-1-13: + acceptance-kind-1-23-consul-compat-nightly-1-13: environment: - TEST_RESULTS: /tmp/test-results - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev" @@ -1218,15 +1270,23 @@ jobs: fail_only: true failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.13 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" +######################## +# WORKFLOWS +######################## +# Workflows are a set of rules for defining a collection of jobs and their run order. +# This is where the pipeline tests and builds are constructed and triggers for running these tests +# are defined workflows: version: 2 test-and-build: jobs: # Build this one control-plane binary so that acceptance and acceptance-tproxy will run - # The rest of these CircleCI jobs have been migrated to Github Actions. We need to wait until - # the summer of 2022 for larger puplic Github Action VMs be available before the acceptance tests can + # The rest of these CircleCI jobs have been migrated to GitHub Actions. We need to wait until + # there is support for a larger pool of runners before the acceptance tests can # be moved - # Run acceptance tests using the docker image built for the control plane + # Run acceptance tests using the docker image built for the control plane for this particular + # branch + # This is run on every PR - build-distro: OS: "linux" ARCH: "amd64 arm64" @@ -1247,14 +1307,33 @@ workflows: context: consul-ci requires: - dev-upload-docker - nightly-acceptance-tests: + + nightly-cleanup: triggers: - schedule: - cron: "0 0 * * *" + cron: "0 12 * * *" # Run at 12 pm UTC (5 am PST) filters: branches: only: - main + jobs: + - cleanup-gcp-resources + - cleanup-azure-resources + - cleanup-eks-resources + + + nightly-acceptance-tests-release: + description: | + Tests which run on a release branch nightly. These exist separate from the main + acceptance tests so that they can run at their own cadence, but + contains the same sequence of jobs. + triggers: + - schedule: + cron: "0 0 * * *" # Run at 12 am UTC (5 pm PST) + filters: + branches: + only: + - release/0.49.x jobs: - build-distro: OS: "linux" @@ -1263,44 +1342,87 @@ workflows: - dev-upload-docker: requires: - build-distros-linux - - cleanup-gcp-resources - - cleanup-azure-resources - - cleanup-eks-resources # Disable until we can use UBI images. - # - acceptance-openshift: - # requires: - # - cleanup-azure-resources + # - acceptance-openshift - acceptance-gke-1-23: requires: - - cleanup-gcp-resources - dev-upload-docker - acceptance-gke-cni-1-23: requires: - acceptance-gke-1-23 - acceptance-eks-1-21: requires: - - cleanup-eks-resources - dev-upload-docker - acceptance-eks-cni-1-21: requires: - acceptance-eks-1-21 - acceptance-aks-1-22: requires: - - cleanup-azure-resources - dev-upload-docker - acceptance-aks-cni-1-22: requires: - acceptance-aks-1-22 + - acceptance-tproxy: + requires: + - dev-upload-docker + + nightly-acceptance-tests-main: + description: | + Tests which run on the main branch nightly. These exist separate from the release + acceptance tests so that they can run at their own cadence, but + contains the same sequence of jobs. + triggers: + - schedule: + cron: "0 0 * * *" # Run at 12 am UTC (5 pm PST) + filters: + branches: + only: + - main + jobs: + - build-distro: + OS: "linux" + ARCH: "amd64 arm64" + name: build-distros-linux + - dev-upload-docker: + requires: + - build-distros-linux + # Disable until we can use UBI images. + # - acceptance-openshift + - acceptance-gke-1-23: + requires: + - dev-upload-docker + - acceptance-gke-cni-1-23: + requires: + - acceptance-gke-1-23 + - acceptance-eks-1-21: + requires: + - dev-upload-docker + - acceptance-eks-cni-1-21: + requires: + - acceptance-eks-1-21 + - acceptance-aks-1-22: + requires: + - dev-upload-docker + - acceptance-aks-cni-1-22: + requires: + - acceptance-aks-1-22 + - acceptance-tproxy: + requires: + - dev-upload-docker - nightly-acceptance-tests-consul: + nightly-kind-acceptance-tests-consul-compatability: + description: | + Acceptance tests which run nightly to verify the compatibility between + a consul-k8s binary and it's consul version pair. Tests will be conducted + for up to n-2 previous Consul-k8s releases. triggers: - schedule: - cron: "0 0 * * *" + cron: "0 0 * * *" # Run at 12 am UTC (5 pm PST) filters: branches: only: - main jobs: - - acceptance-kind-1-23-consul-nightly-1-11 - - acceptance-kind-1-23-consul-nightly-1-12 - - acceptance-kind-1-23-consul-nightly-1-13 + - acceptance-kind-1-23-consul-compat-nightly-1-11 + - acceptance-kind-1-23-consul-compat-nightly-1-12 + - acceptance-kind-1-23-consul-compat-nightly-1-13 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ec825cafd2..14875e1d55 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -614,6 +614,9 @@ To run a specific test by name use the `--filter` flag: ```bash brew install gox ``` + ```bash + make cli-dev + ``` To run the acceptance tests: cd acceptance/tests From 9629d8fffedbb5b28b046b68c1725bddfd5794f1 Mon Sep 17 00:00:00 2001 From: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:39:44 -0500 Subject: [PATCH 174/235] Merge pull request #1650 from hashicorp/consul-api-gateway-add-tolerations-support Consul API Gateway, Add Tolerations support --- CHANGELOG.md | 1 + .../api-gateway-controller-deployment.yaml | 4 ++++ .../templates/api-gateway-gatewayclassconfig.yaml | 6 +++++- charts/consul/values.yaml | 13 +++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c225748fbf..0e1fbf53b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ IMPROVEMENTS: * Helm: * Add `tolerations` and `nodeSelector` to Server ACL init jobs and `nodeSelector` to Webhook cert manager. [[GH-1581](https://github.com/hashicorp/consul-k8s/pull/1581)] * API Gateway: Allow controller to read MeshServices for use as a route backend. [[GH-1574](https://github.com/hashicorp/consul-k8s/pull/1574)] + * API Gateway: Add `tolerations` to `apiGateway.managedGatewayClass` and `apiGateway.controller` [[GH-1650](https://github.com/hashicorp/consul-k8s/pull/1650)] * API Gateway: Create PodSecurityPolicy for controller when `global.enablePodSecurityPolicies=true`. [[GH-1656](https://github.com/hashicorp/consul-k8s/pull/1656)] ## 0.49.0 (September 30, 2022) diff --git a/charts/consul/templates/api-gateway-controller-deployment.yaml b/charts/consul/templates/api-gateway-controller-deployment.yaml index 22d14c1e48..604a017ecf 100644 --- a/charts/consul/templates/api-gateway-controller-deployment.yaml +++ b/charts/consul/templates/api-gateway-controller-deployment.yaml @@ -235,4 +235,8 @@ spec: nodeSelector: {{ tpl .Values.apiGateway.controller.nodeSelector . | indent 8 | trim }} {{- end }} + {{- if .Values.apiGateway.controller.tolerations }} + tolerations: + {{ tpl .Values.apiGateway.controller.tolerations . | indent 8 | trim }} + {{- end }} {{- end }} diff --git a/charts/consul/templates/api-gateway-gatewayclassconfig.yaml b/charts/consul/templates/api-gateway-gatewayclassconfig.yaml index 6394671528..450357a773 100644 --- a/charts/consul/templates/api-gateway-gatewayclassconfig.yaml +++ b/charts/consul/templates/api-gateway-gatewayclassconfig.yaml @@ -35,10 +35,14 @@ spec: image: consulAPIGateway: {{ .Values.apiGateway.image }} envoy: {{ .Values.global.imageEnvoy }} - {{- if .Values.apiGateway.nodeSelector }} + {{- if .Values.apiGateway.managedGatewayClass.nodeSelector }} nodeSelector: {{ tpl .Values.apiGateway.managedGatewayClass.nodeSelector . | indent 4 | trim }} {{- end }} + {{- if .Values.apiGateway.managedGatewayClass.tolerations }} + tolerations: + {{ tpl .Values.apiGateway.managedGatewayClass.tolerations . | indent 4 | trim }} + {{- end }} {{- if .Values.apiGateway.managedGatewayClass.copyAnnotations.service }} copyAnnotations: service: diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 1cbd709576..564de43780 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -2956,6 +2956,13 @@ apiGateway: # @type: string nodeSelector: null + # This value defines the tolerations that will be assigned to a gateway pod. + # This should be a multi-line string matching the + # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + # + # @type: string + tolerations: null + # This value defines the type of service created for gateways (e.g. LoadBalancer, ClusterIP) serviceType: LoadBalancer @@ -3038,6 +3045,12 @@ apiGateway: # @type: string nodeSelector: null + # This value defines the tolerations for api-gateway-controller pod, this should be a multi-line string matching the + # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + # + # @type: string + tolerations: null + # Configuration for the Service created for the api-gateway-controller service: # Annotations to apply to the api-gateway-controller service. From c54bafb041b7f2ddaf3787290a770fa8789edf49 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Mon, 7 Nov 2022 07:16:06 -0800 Subject: [PATCH 175/235] api-gateway: allow controller to bind PodSecurityPolicy to ServiceAccounts that it creates (#1672) (#1682) * Add PodSecurityPolicy for all Gateway Deployments * Allow API gateway controller to manage roles + bindings * Add entry to CHANGELOG * Consolidate controller ClusterRole mods for enablePodSecurityPolicies * Update/add unit test coverage for controller ClusterRole * Check for additional verbs on cluster role Co-authored-by: Nathan Coleman --- CHANGELOG.md | 1 + .../api-gateway-controller-clusterrole.yaml | 20 ++++++--- .../api-gateway-gatewayclassconfig.yaml | 3 ++ .../api-gateway-podsecuritypolicy.yaml | 45 +++++++++++++++++++ .../api-gateway-controller-clusterrole.bats | 16 ++++++- 5 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 charts/consul/templates/api-gateway-podsecuritypolicy.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e1fbf53b3..4ce8d8aca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ IMPROVEMENTS: * API Gateway: Allow controller to read MeshServices for use as a route backend. [[GH-1574](https://github.com/hashicorp/consul-k8s/pull/1574)] * API Gateway: Add `tolerations` to `apiGateway.managedGatewayClass` and `apiGateway.controller` [[GH-1650](https://github.com/hashicorp/consul-k8s/pull/1650)] * API Gateway: Create PodSecurityPolicy for controller when `global.enablePodSecurityPolicies=true`. [[GH-1656](https://github.com/hashicorp/consul-k8s/pull/1656)] + * API Gateway: Create PodSecurityPolicy and allow controller to bind it to ServiceAccounts that it creates for Gateway Deployments when `global.enablePodSecurityPolicies=true`. [[GH-1672](https://github.com/hashicorp/consul-k8s/pull/1672)] ## 0.49.0 (September 30, 2022) diff --git a/charts/consul/templates/api-gateway-controller-clusterrole.yaml b/charts/consul/templates/api-gateway-controller-clusterrole.yaml index f84c5561c2..eac2bd1f69 100644 --- a/charts/consul/templates/api-gateway-controller-clusterrole.yaml +++ b/charts/consul/templates/api-gateway-controller-clusterrole.yaml @@ -245,11 +245,21 @@ rules: - patch - update {{- if .Values.global.enablePodSecurityPolicies }} -- apiGroups: ["policy"] - resources: ["podsecuritypolicies"] - resourceNames: - - {{ template "consul.fullname" . }}-api-gateway-controller +- apiGroups: + - policy + resources: + - podsecuritypolicies + verbs: + - use +- apiGroups: + - rbac.authorization.k8s.io + resources: + - roles + - rolebindings verbs: - - use + - create + - get + - list + - watch {{- end }} {{- end }} diff --git a/charts/consul/templates/api-gateway-gatewayclassconfig.yaml b/charts/consul/templates/api-gateway-gatewayclassconfig.yaml index 450357a773..f2fecba47e 100644 --- a/charts/consul/templates/api-gateway-gatewayclassconfig.yaml +++ b/charts/consul/templates/api-gateway-gatewayclassconfig.yaml @@ -15,6 +15,9 @@ spec: {{- if .Values.global.acls.manageSystemACLs }} managed: true method: {{ template "consul.fullname" . }}-k8s-auth-method + {{- if .Values.global.enablePodSecurityPolicies }} + podSecurityPolicy: {{ template "consul.fullname" . }}-api-gateway + {{- end }} {{- end }} {{- if .Values.global.tls.enabled }} scheme: https diff --git a/charts/consul/templates/api-gateway-podsecuritypolicy.yaml b/charts/consul/templates/api-gateway-podsecuritypolicy.yaml new file mode 100644 index 0000000000..48f826f995 --- /dev/null +++ b/charts/consul/templates/api-gateway-podsecuritypolicy.yaml @@ -0,0 +1,45 @@ +{{- if and .Values.apiGateway.enabled .Values.global.enablePodSecurityPolicies }} +apiVersion: policy/v1beta1 +kind: PodSecurityPolicy +metadata: + name: {{ template "consul.fullname" . }}-api-gateway + namespace: {{ .Release.Namespace }} + labels: + app: {{ template "consul.name" . }} + chart: {{ template "consul.chart" . }} + heritage: {{ .Release.Service }} + release: {{ .Release.Name }} + component: api-gateway-controller +spec: + privileged: false + # Required to prevent escalations to root. + allowPrivilegeEscalation: false + # This is redundant with non-root + disallow privilege escalation, + # but we can provide it for defense in depth. + requiredDropCapabilities: + - ALL + # Allow core volume types. + volumes: + - 'configMap' + - 'emptyDir' + - 'projected' + - 'secret' + - 'downwardAPI' + allowedCapabilities: + - NET_BIND_SERVICE + hostNetwork: false + hostIPC: false + hostPID: false + hostPorts: + - max: 65535 + min: 1025 + runAsUser: + rule: 'RunAsAny' + seLinux: + rule: 'RunAsAny' + supplementalGroups: + rule: 'RunAsAny' + fsGroup: + rule: 'RunAsAny' + readOnlyRootFilesystem: true +{{- end }} diff --git a/charts/consul/test/unit/api-gateway-controller-clusterrole.bats b/charts/consul/test/unit/api-gateway-controller-clusterrole.bats index b69b6ac966..f26fdfeebd 100644 --- a/charts/consul/test/unit/api-gateway-controller-clusterrole.bats +++ b/charts/consul/test/unit/api-gateway-controller-clusterrole.bats @@ -20,7 +20,7 @@ load _helpers [ "${actual}" = "true" ] } -@test "apiGateway/ClusterRole: uses PodSecurityPolicy with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { +@test "apiGateway/ClusterRole: can use podsecuritypolicies with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { cd `chart_dir` local actual=$(helm template \ -s templates/api-gateway-controller-clusterrole.yaml \ @@ -28,6 +28,18 @@ load _helpers --set 'apiGateway.enabled=true' \ --set 'apiGateway.image=foo' \ . | tee /dev/stderr | - yq '.rules[] | select((.resourceNames[0] == "release-name-consul-api-gateway-controller") and (.resources[0] == "podsecuritypolicies")) | length > 0' | tee /dev/stderr) + yq '.rules[] | select((.resources[0] == "podsecuritypolicies") and (.verbs[0] == "use")) | length > 0' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + +@test "apiGateway/ClusterRole: can create roles and rolebindings with apiGateway.enabled=true and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-clusterrole.yaml \ + --set 'global.enablePodSecurityPolicies=true' \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=foo' \ + . | tee /dev/stderr | + yq '.rules[] | select((.resources[0] == "roles") and (.resources[1] == "rolebindings") and (.verbs | contains(["create","get","list","watch"]))) | length > 0' | tee /dev/stderr) [ "${actual}" = "true" ] } From b50036bbf37f34b639c4cbad98e50c88180aa611 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Tue, 8 Nov 2022 13:35:27 -0800 Subject: [PATCH 176/235] Mw/release/0.49.x/fix cloud pipeline (#1679) * updated libraries based on main, especially helm - resolved an issue with terraform provisioned aws version incompatibility with helm, also updated helm - we are not supporting eks testing for release branches, but this fix will stay in * disabling peering tests as these are a beta feature - peering tests are not fully supported for 0.49 and tests can fail intermittently * update test dockerfile to handle gcloud deprecations - this dockerfile more closely matches what is found in main, the big difference being that 0.49 supports go 1.18 instead of 1.19 (at the time of this commit) - added a new make target for creating the test docker image * created a new workflow for running nightly release branch tests - only run a single cloud test (arbitrarily GKE) and kind testing. A single cloud test is sufficient for release branch testing - gcloud plugin enabled to handle deprecations with older gke cli - updated consul-helm-test-image to latest version --- .circleci/config.yml | 19 +- acceptance/go.sum | 44 - acceptance/tests/peering/main_test.go | 19 +- charts/consul/test/docker/Test.dockerfile | 12 +- charts/consul/test/terraform/eks/main.tf | 5 +- cli/go.mod | 171 ++-- cli/go.sum | 1093 ++++++++++----------- control-plane/Makefile | 21 + 8 files changed, 675 insertions(+), 709 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 8bf43c4378..05f6a209e9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,14 +16,13 @@ cli-path: &cli-path cli acceptance-mod-path: &acceptance-mod-path acceptance acceptance-test-path: &acceptance-test-path acceptance/tests acceptance-framework-path: &acceptance-framework-path acceptance/framework -charts-consul-path: &charts-consul-path charts/consul helm-gen-path: &helm-gen-path hack/helm-reference-gen gke-terraform-path: &gke-terraform-path charts/consul/test/terraform/gke eks-terraform-path: &eks-terraform-path charts/consul/test/terraform/eks aks-terraform-path: &aks-terraform-path charts/consul/test/terraform/aks openshift-terraform-path: &openshift-terraform-path charts/consul/test/terraform/openshift -# This image is built from test/docker/Test.dockerfile -consul-helm-test-image: &consul-helm-test-image docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 +# This image is built from charts/consul/test/docker/Test.dockerfile and provides the necessary dependencies for running on our cloud targets. +consul-helm-test-image: &consul-helm-test-image docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.3 ######################## # COMMANDS @@ -728,6 +727,7 @@ jobs: parallelism: 2 environment: - TEST_RESULTS: /tmp/test-results + - USE_GKE_GCLOUD_AUTH_PLUGIN: true docker: - image: *consul-helm-test-image @@ -796,6 +796,7 @@ jobs: parallelism: 2 environment: - TEST_RESULTS: /tmp/test-results + - USE_GKE_GCLOUD_AUTH_PLUGIN: true docker: - image: *consul-helm-test-image @@ -1350,18 +1351,6 @@ workflows: - acceptance-gke-cni-1-23: requires: - acceptance-gke-1-23 - - acceptance-eks-1-21: - requires: - - dev-upload-docker - - acceptance-eks-cni-1-21: - requires: - - acceptance-eks-1-21 - - acceptance-aks-1-22: - requires: - - dev-upload-docker - - acceptance-aks-cni-1-22: - requires: - - acceptance-aks-1-22 - acceptance-tproxy: requires: - dev-upload-docker diff --git a/acceptance/go.sum b/acceptance/go.sum index c4e8c9b20e..8bb13efef3 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -184,8 +184,6 @@ github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/frankban/quicktest v1.10.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.13.0 h1:yNZif1OkDfNoDfb9zZa9aXIpejNR4F23Wely0c+Qdqk= @@ -264,10 +262,7 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -281,7 +276,6 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-containerregistry v0.0.0-20200110202235-f4fb41bf00a3/go.mod h1:2wIuQute9+hhWqvL3vEI7YB0EKluF4WcPzI1eAliazk= @@ -324,11 +318,8 @@ github.com/gruntwork-io/terratest v0.31.2 h1:xvYHA80MUq5kx670dM18HInewOrrQrAN+Xb github.com/gruntwork-io/terratest v0.31.2/go.mod h1:EEgJie28gX/4AD71IFqgMj6e99KP5mi81hEtzmDjxTo= github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638 h1:z68s6H6O3RjxDmNvou/2/3UBrsJkrMcNzI0IQN5scAM= github.com/hashicorp/consul-k8s/control-plane v0.0.0-20211207212234-aea9efea5638/go.mod h1:7ZeaiADGbvJDuoWAT8UKj6KCcLsFUk+34OkUGMVtdXg= -github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df h1:CCh336XUGPaMNqMkzRAeEL0BFin7LhX729xy3IxE5Y4= -github.com/hashicorp/consul/api v1.10.1-0.20220726130109-a6a79d6811df/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk= github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= -github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI= github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= @@ -391,8 +382,6 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM= github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= @@ -493,8 +482,6 @@ github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -509,10 +496,7 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= @@ -526,7 +510,6 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -534,7 +517,6 @@ github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU= github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -630,8 +612,6 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= @@ -744,14 +724,10 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= @@ -818,21 +794,14 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -899,10 +868,8 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -949,8 +916,6 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -980,11 +945,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1031,13 +993,9 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.17.0/go.mod h1:npsyOePkeP0CPwyGfXDHxvypiYMJxBWAMpQxCaJ4ZxI= k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= -k8s.io/api v0.19.3/go.mod h1:VF+5FT1B74Pw3KxMdKyinLo+zynBaMBiAfGMuldcNDs= k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= -k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= -k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= -k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= k8s.io/apimachinery v0.19.3/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= @@ -1078,8 +1036,6 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8 rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= diff --git a/acceptance/tests/peering/main_test.go b/acceptance/tests/peering/main_test.go index 12bb35afd5..2a5bf4b448 100644 --- a/acceptance/tests/peering/main_test.go +++ b/acceptance/tests/peering/main_test.go @@ -10,13 +10,18 @@ import ( var suite testsuite.Suite +// TestMain for peering is DISABLED for 0.49. func TestMain(m *testing.M) { - suite = testsuite.NewSuite(m) - if suite.Config().EnableMultiCluster && !suite.Config().DisablePeering { - os.Exit(suite.Run()) - } else { - fmt.Println("Skipping peering tests because either -enable-multi-cluster is not set or -disable-peering is set") - os.Exit(0) - } + fmt.Println("Skipping peering tests because this is a beta feature and not fully supported") + os.Exit(0) + + //suite = testsuite.NewSuite(m) + // + //if suite.Config().EnableMultiCluster && !suite.Config().DisablePeering { + // os.Exit(suite.Run()) + //} else { + // fmt.Println("Skipping peering tests because either -enable-multi-cluster is not set or -disable-peering is set") + // os.Exit(0) + //} } diff --git a/charts/consul/test/docker/Test.dockerfile b/charts/consul/test/docker/Test.dockerfile index 2fccf196d3..d60e8b0a24 100644 --- a/charts/consul/test/docker/Test.dockerfile +++ b/charts/consul/test/docker/Test.dockerfile @@ -27,7 +27,11 @@ RUN apt-get install -y \ RUN pip3 install yq # gcloud -RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && apt-get update -y && apt-get install google-cloud-sdk -y +RUN echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \ + curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && \ + apt-get update -y && \ + apt-get install google-cloud-sdk -y && \ + apt-get install google-cloud-sdk-gke-gcloud-auth-plugin # terraform RUN curl -sSL https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -o /tmp/tf.zip \ @@ -57,16 +61,16 @@ RUN curl -sSL https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/o && mv /tmp/oc /usr/local/bin/oc # AWS CLI -RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-2.8.3.zip" -o "awscliv2.zip" \ && unzip awscliv2.zip \ && ./aws/install --bin-dir /usr/local/bin \ && rm awscliv2.zip \ && rm -rf ./aws # AWS IAM authenticator -RUN curl -o aws-iam-authenticator https://amazon-eks.s3.us-west-2.amazonaws.com/1.18.9/2020-11-02/bin/linux/amd64/aws-iam-authenticator \ +RUN curl -Lo aws-iam-authenticator https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v0.5.9/aws-iam-authenticator_0.5.9_linux_amd64 \ && chmod +x ./aws-iam-authenticator \ && mv ./aws-iam-authenticator /usr/local/bin/aws-iam-authenticator # change the user back to what circleci/golang image has -USER circleci +USER circleci \ No newline at end of file diff --git a/charts/consul/test/terraform/eks/main.tf b/charts/consul/test/terraform/eks/main.tf index 19b8cb1229..9ccc2cdd2b 100644 --- a/charts/consul/test/terraform/eks/main.tf +++ b/charts/consul/test/terraform/eks/main.tf @@ -53,8 +53,9 @@ module "vpc" { module "eks" { count = var.cluster_count - source = "terraform-aws-modules/eks/aws" - version = "17.20.0" + source = "terraform-aws-modules/eks/aws" + version = "17.24.0" + kubeconfig_api_version = "client.authentication.k8s.io/v1beta1" cluster_name = "consul-k8s-${random_id.suffix[count.index].dec}" cluster_version = "1.21" diff --git a/cli/go.mod b/cli/go.mod index 00c718a139..cd95397863 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -5,158 +5,157 @@ go 1.18 require ( github.com/bgentry/speakeasy v0.1.0 github.com/cenkalti/backoff v2.2.1+incompatible - github.com/fatih/color v1.9.0 - github.com/google/go-cmp v0.5.5 + github.com/fatih/color v1.13.0 + github.com/google/go-cmp v0.5.8 github.com/hashicorp/consul-k8s/charts v0.0.0-00010101000000-000000000000 github.com/hashicorp/go-hclog v0.16.2 github.com/kr/text v0.2.0 - github.com/mattn/go-isatty v0.0.12 + github.com/mattn/go-isatty v0.0.14 github.com/mitchellh/cli v1.1.2 - github.com/olekukonko/tablewriter v0.0.4 + github.com/olekukonko/tablewriter v0.0.5 github.com/posener/complete v1.1.1 - github.com/stretchr/testify v1.7.0 - helm.sh/helm/v3 v3.6.1 - k8s.io/api v0.22.2 - k8s.io/apimachinery v0.22.2 - k8s.io/cli-runtime v0.21.0 - k8s.io/client-go v0.22.2 - k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a - sigs.k8s.io/yaml v1.2.0 + github.com/stretchr/testify v1.7.2 + helm.sh/helm/v3 v3.9.4 + k8s.io/api v0.25.0 + k8s.io/apimachinery v0.25.0 + k8s.io/cli-runtime v0.24.3 + k8s.io/client-go v0.25.0 + k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed + sigs.k8s.io/yaml v1.3.0 ) require ( - cloud.google.com/go v0.54.0 // indirect + cloud.google.com/go v0.99.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.18 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect + github.com/Azure/go-autorest/autorest v0.11.27 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.20 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/logger v0.2.1 // indirect github.com/Azure/go-autorest/tracing v0.6.0 // indirect - github.com/BurntSushi/toml v0.3.1 // indirect + github.com/BurntSushi/toml v1.0.0 // indirect github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect github.com/Masterminds/sprig/v3 v3.2.2 // indirect - github.com/Masterminds/squirrel v1.5.0 // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect - github.com/Microsoft/hcsshim v0.8.14 // indirect + github.com/Masterminds/squirrel v1.5.3 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 // indirect - github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect + github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 // indirect - github.com/containerd/containerd v1.4.4 // indirect - github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 // indirect - github.com/cyphar/filepath-securejoin v0.2.2 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect + github.com/containerd/containerd v1.6.6 // indirect + github.com/cyphar/filepath-securejoin v0.2.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/deislabs/oras v0.11.1 // indirect - github.com/docker/cli v20.10.5+incompatible // indirect - github.com/docker/distribution v2.7.1+incompatible // indirect - github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible // indirect - github.com/docker/docker-credential-helpers v0.6.3 // indirect + github.com/docker/cli v20.10.17+incompatible // indirect + github.com/docker/distribution v2.8.1+incompatible // indirect + github.com/docker/docker v20.10.17+incompatible // indirect + github.com/docker/docker-credential-helpers v0.6.4 // indirect github.com/docker/go-connections v0.4.0 // indirect - github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 // indirect + github.com/docker/go-metrics v0.0.1 // indirect github.com/docker/go-units v0.4.0 // indirect - github.com/evanphx/json-patch v4.11.0+incompatible // indirect + github.com/emicklei/go-restful/v3 v3.8.0 // indirect + github.com/evanphx/json-patch v4.12.0+incompatible // indirect github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect - github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-errors/errors v1.0.1 // indirect - github.com/go-logr/logr v0.4.0 // indirect - github.com/go-openapi/jsonpointer v0.19.3 // indirect - github.com/go-openapi/jsonreference v0.19.3 // indirect - github.com/go-openapi/spec v0.19.5 // indirect + github.com/go-gorp/gorp/v3 v3.0.2 // indirect + github.com/go-logr/logr v1.2.3 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gobwas/glob v0.2.3 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang-jwt/jwt/v4 v4.2.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/btree v1.0.1 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gnostic v0.5.7-v3refs // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/googleapis/gnostic v0.5.5 // indirect - github.com/gorilla/mux v1.7.3 // indirect + github.com/google/uuid v1.2.0 // indirect + github.com/gorilla/mux v1.8.0 // indirect github.com/gosuri/uitable v0.0.4 // indirect github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect - github.com/hashicorp/errwrap v1.0.0 // indirect - github.com/hashicorp/go-multierror v1.1.0 // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/huandu/xstrings v1.3.2 // indirect - github.com/imdario/mergo v0.3.11 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/jmoiron/sqlx v1.3.1 // indirect + github.com/jmoiron/sqlx v1.3.5 // indirect github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.11 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.13.6 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect - github.com/lib/pq v1.10.0 // indirect + github.com/lib/pq v1.10.6 // indirect github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect - github.com/mattn/go-colorable v0.1.8 // indirect - github.com/mattn/go-runewidth v0.0.7 // indirect + github.com/mattn/go-colorable v0.1.12 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect - github.com/mitchellh/copystructure v1.1.1 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/mitchellh/reflectwalk v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/moby/locker v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect - github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect + github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.1 // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/onsi/ginkgo v1.16.5 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect - github.com/opencontainers/image-spec v1.0.1 // indirect - github.com/opencontainers/runc v0.1.1 // indirect + github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.11.0 // indirect + github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.26.0 // indirect - github.com/prometheus/procfs v0.6.0 // indirect - github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 // indirect + github.com/prometheus/common v0.32.1 // indirect + github.com/prometheus/procfs v0.7.3 // indirect + github.com/rubenv/sql-migrate v1.1.1 // indirect github.com/russross/blackfriday v1.5.2 // indirect github.com/shopspring/decimal v1.2.0 // indirect github.com/sirupsen/logrus v1.8.1 // indirect - github.com/spf13/cast v1.3.1 // indirect - github.com/spf13/cobra v1.1.3 // indirect + github.com/spf13/cast v1.4.1 // indirect + github.com/spf13/cobra v1.4.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect - go.opencensus.io v0.22.3 // indirect go.starlark.net v0.0.0-20200707032745-474f21a9602d // indirect - golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect + golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect + golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect + golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect + golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect - google.golang.org/appengine v1.6.5 // indirect - google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a // indirect - google.golang.org/grpc v1.36.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/gorp.v1 v1.7.2 // indirect + golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect + google.golang.org/grpc v1.47.0 // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - k8s.io/apiextensions-apiserver v0.21.0 // indirect - k8s.io/apiserver v0.21.0 // indirect - k8s.io/component-base v0.21.0 // indirect - k8s.io/klog/v2 v2.9.0 // indirect - k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e // indirect - k8s.io/kubectl v0.21.0 // indirect - rsc.io/letsencrypt v0.0.3 // indirect - sigs.k8s.io/kustomize/api v0.8.5 // indirect - sigs.k8s.io/kustomize/kyaml v0.10.15 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.1.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.25.0 // indirect + k8s.io/apiserver v0.25.0 // indirect + k8s.io/component-base v0.25.0 // indirect + k8s.io/klog/v2 v2.70.1 // indirect + k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect + k8s.io/kubectl v0.24.2 // indirect + oras.land/oras-go v1.2.0 // indirect + sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect + sigs.k8s.io/kustomize/api v0.11.4 // indirect + sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) // This replace directive is to avoid having to manually bump the version of the charts module upon changes to the Helm diff --git a/cli/go.sum b/cli/go.sum index d65d9b4ff1..531cb6f202 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -9,50 +8,69 @@ cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0= cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= +cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= +cloud.google.com/go v0.99.0 h1:y/cM2iqGgGi5D5DQZl6D9STN/3dR/Vx5Mp8s752oJTY= +cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= -github.com/Azure/go-ansiterm v0.0.0-20210608223527-2377c96fe795/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= -github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= -github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= +github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A= +github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= +github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg= +github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= -github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= -github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw= +github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= +github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= @@ -66,285 +84,190 @@ github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZC github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= -github.com/Masterminds/squirrel v1.5.0 h1:JukIZisrUXadA9pl3rMkjhiamxiB0cXiu+HGp/Y8cY8= -github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= -github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= -github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= -github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= -github.com/Microsoft/hcsshim v0.8.14 h1:lbPVK25c1cu5xTLITwpUcxoA9vKrKErASPYygvouJns= -github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= +github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc= +github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= +github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= -github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= -github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= -github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY= -github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= -github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= +github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= -github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1 h1:pgAtgj+A31JBVtEHu2uHuEx0n+2ukqUJnS2vVe5pQNA= -github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= -github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ= -github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o= -github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59 h1:qWj4qVYZ95vLWwqyNJCQg7rDsG5wPdze0UaPolH7DUk= -github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= -github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= -github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/containerd v1.4.4 h1:rtRG4N6Ct7GNssATwgpvMGfnjnwfjnu/Zs9W3Ikzq+M= -github.com/containerd/containerd v1.4.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= -github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7 h1:6ejg6Lkk8dskcM7wQ28gONkukbQkM4qpj4RnYbpFzrI= -github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= -github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= -github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= -github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= -github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= -github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4= +github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0= +github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg= -github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= +github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI= +github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= -github.com/deislabs/oras v0.11.1 h1:oo2J/3vXdcti8cjFi8ghMOkx0OacONxHC8dhJ17NdJ0= -github.com/deislabs/oras v0.11.1/go.mod h1:39lCtf8Q6WDC7ul9cnyWXONNzKvabEKk+AX+L0ImnQk= -github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= -github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= -github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= -github.com/docker/cli v20.10.5+incompatible h1:bjflayQbWg+xOkF2WPEAOi4Y7zWhR7ptoPhV/VqLVDE= -github.com/docker/cli v20.10.5+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= -github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug= -github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible h1:iWPIG7pWIsCwT6ZtHnTUpoVMnete7O/pzd9HFE3+tn8= -github.com/docker/docker v17.12.0-ce-rc1.0.20200618181300-9dc6525e6118+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.6.3 h1:zI2p9+1NQYdnG6sMU26EX4aVGlqbInSQxQXLvzJ4RPQ= -github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/distribution/distribution/v3 v3.0.0-20220526142353-ffbd94cbe269 h1:hbCT8ZPPMqefiAWD2ZKjn7ypokIGViTvBBg/ExLSdCk= +github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M= +github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= +github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o= +github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916 h1:yWHOI+vFjEsAakUTSrtqc/SAHrhSkmn48pqjidZX3QA= -github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= -github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= +github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= +github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4= -github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= +github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs= github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= +github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= -github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= +github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7 h1:LofdAjjjqCSXMwLGgOgnE+rdPuvX9DxCqaHwKy7i/ko= -github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= +github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-gorp/gorp/v3 v3.0.2 h1:ULqJXIekoqMx29FI5ekXXFoH1dT2Vc8UhnRzBg+Emz4= +github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= -github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= -github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= -github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.5 h1:Xm0Ao53uqnk9QE/LlYV5DEU09UAgpliA85QoT9LzqPw= -github.com/go-openapi/spec v0.19.5/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= -github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= -github.com/go-openapi/strfmt v0.19.5/go.mod h1:eftuHTlB/dI8Uq8JJOyRlieZf+WkkxUuk0dgdHXr2Qk= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= +github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= -github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= -github.com/gobuffalo/envy v1.7.1 h1:OQl5ys5MBea7OGCdvPbBJWRgnhC/fGona6QKfvFeau8= -github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= -github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= -github.com/gobuffalo/logger v1.0.1 h1:ZEgyRGgAm4ZAhAO45YXMs5Fp+bzGLESFewzAVBMKuTg= -github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= -github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4= -github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= -github.com/gobuffalo/packr/v2 v2.7.1 h1:n3CIW5T17T8v4GGK5sWXLVWJhCz7b5aNLSxW6gYim4o= -github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= +github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs= +github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= +github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= +github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= +github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= -github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= +github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU= +github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -355,11 +278,16 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= @@ -369,85 +297,94 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk= +github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= +github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= +github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= +github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= -github.com/googleapis/gnostic v0.5.5 h1:9fHAtK0uDfpveeqqo1hkEZJcFvYXAiCN3UutL8F9xHw= -github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo= -github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= -github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.16.2 h1:K4ev2ib4LdQETX5cSZBG0DVLk1jwGqSPXBjdah3veNs= github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= -github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -460,48 +397,47 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jmoiron/sqlx v1.3.1 h1:aLN7YINNZ7cYOPK3QC83dbM6KT0NMqVMw961TqrejlE= -github.com/jmoiron/sqlx v1.3.1/go.mod h1:2BljVx/86SuTyjE+aPYlHCTNvZrnJXghYGpNiXLBMCQ= -github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= -github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= +github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= -github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= +github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= +github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -510,43 +446,40 @@ github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtB github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.0 h1:Zx5DJFEYQXio93kgXnQ09fXNiUKsqv4OUEu2UtGcB1E= github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs= +github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= -github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= +github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc= +github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= +github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI= +github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= +github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= -github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mattn/go-shellwords v1.0.11/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= -github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= @@ -557,10 +490,9 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/cli v1.1.2 h1:PvH+lL2B7IQ101xQL63Of8yFS2y+aDlsFcsqNc+u/Kw= github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/copystructure v1.1.1 h1:Bp6x9R1Wn16SIz3OfeDr0b7RnCG2OB66Y7PQyC/cvq4= -github.com/mitchellh/copystructure v1.1.1/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= @@ -569,202 +501,138 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= -github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= +github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/term v0.0.0-20201216013528-df9cb8a40635/go.mod h1:FBS0z0QWA44HXygs7VXDUOGoN/1TV3RuWkLO04am3wc= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 h1:yH0SvLzcbZxcJXho2yh7CqdENGMQe73Cw3woZBpPli0= -github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A= +github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= +github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= -github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2fSBUmeGDbRWPxyQ= -github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= -github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= -github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= +github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y= -github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= -github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec= +github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= 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= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= -github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1 h1:oL4IBbcqwhhNWh31bjOX8C/OCy0zs9906d/VUru+bqg= +github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= -github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= -github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.4.0 h1:LUa41nrWTQNGhzdsZ5lTnkwbNjj6rXTdazA1cSdjkOY= -github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351 h1:HXr/qUllAWv9riaI4zh2eXWKmCSDqVS/XH1MRHLKRwk= -github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rubenv/sql-migrate v1.1.1 h1:haR5Hn8hbW9/SpAICrXoZqXnywS7Q5WijwkQENPeNWY= +github.com/rubenv/sql-migrate v1.1.1/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= -github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= -github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= -github.com/spf13/cobra v1.1.3 h1:xghbfqPkxzxP3C/f3n5DdpAbdKLj4ZE4BWQI362l53M= -github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSWzOo= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= +github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= +github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= @@ -774,85 +642,77 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca h1:1CFlNzQhALwjS9mBAUkycX616GzgsuYUOCHA5+HSlXI= github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI= -github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE= -github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY= -github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= -go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.20.0/go.mod h1:2AboqHi0CiIZU0qwhtUfCYD1GeUzvvIXWNkhDt7ZMG4= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/exporters/otlp v0.20.0/go.mod h1:YIieizyaN77rtLJra0buKiNBOm9XQfkPEKBeuhoMwAM= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE= +go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.starlark.net v0.0.0-20200707032745-474f21a9602d h1:uFqwFYlX7d5ZSp+IqhXxct0SybXrTzEBDvb2CkEhPBs= go.starlark.net v0.0.0-20200707032745-474f21a9602d/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= +golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -875,6 +735,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= @@ -883,32 +745,28 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -916,116 +774,161 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= +golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= -golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= +golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1035,17 +938,13 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1054,7 +953,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -1062,18 +960,38 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1083,21 +1001,41 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= +google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1110,27 +1048,80 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a h1:pOwg4OoaRYScjmR4LlLgdtnyoHYTSAVhhqe5uPdpII8= -google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I= +google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.36.0 h1:o1bcQ6imQMIOpdrO3SWf2z5RV72WbDwdXuK0MDlc8As= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1143,110 +1134,110 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= -gopkg.in/gorp.v1 v1.7.2 h1:j3DWlAyGVv8whO7AcIWznQ2Yj7yJkn34B8s63GViAAw= -gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= -gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= -gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -helm.sh/helm/v3 v3.6.1 h1:TQ6q4pAatXr7qh2fbLcb0oNd0I3J7kv26oo5cExKTtc= -helm.sh/helm/v3 v3.6.1/go.mod h1:mIIus8EOqj+obtycw3sidsR4ORr2aFDmXMSI3k+oeVY= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +helm.sh/helm/v3 v3.9.4 h1:TCI1QhJUeLVOdccfdw+vnSEO3Td6gNqibptB04QtExY= +helm.sh/helm/v3 v3.9.4/go.mod h1:3eaWAIqzvlRSD06gR9MMwmp2KBKwlu9av1/1BZpjeWY= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.21.0/go.mod h1:+YbrhBBGgsxbF6o6Kj4KJPJnBmAKuXDeS3E18bgHNVU= -k8s.io/api v0.22.2 h1:M8ZzAD0V6725Fjg53fKeTJxGsJvRbk4TEm/fexHMtfw= -k8s.io/api v0.22.2/go.mod h1:y3ydYpLJAaDI+BbSe2xmGcqxiWHmWjkEeIbiwHvnPR8= -k8s.io/apiextensions-apiserver v0.21.0 h1:Nd4uBuweg6ImzbxkC1W7xUNZcCV/8Vt10iTdTIVF3hw= -k8s.io/apiextensions-apiserver v0.21.0/go.mod h1:gsQGNtGkc/YoDG9loKI0V+oLZM4ljRPjc/sql5tmvzc= -k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY= -k8s.io/apimachinery v0.22.2 h1:ejz6y/zNma8clPVfNDLnPbleBo6MpoFy/HBiBqCouVk= -k8s.io/apimachinery v0.22.2/go.mod h1:O3oNtNadZdeOMxHFVxOreoznohCpy0z6mocxbZr7oJ0= -k8s.io/apiserver v0.21.0 h1:1hWMfsz+cXxB77k6/y0XxWxwl6l9OF26PC9QneUVn1Q= -k8s.io/apiserver v0.21.0/go.mod h1:w2YSn4/WIwYuxG5zJmcqtRdtqgW/J2JRgFAqps3bBpg= -k8s.io/cli-runtime v0.21.0 h1:/V2Kkxtf6x5NI2z+Sd/mIrq4FQyQ8jzZAUD6N5RnN7Y= -k8s.io/cli-runtime v0.21.0/go.mod h1:XoaHP93mGPF37MkLbjGVYqg3S1MnsFdKtiA/RZzzxOo= -k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA= -k8s.io/client-go v0.22.2 h1:DaSQgs02aCC1QcwUdkKZWOeaVsQjYvWv8ZazcZ6JcHc= -k8s.io/client-go v0.22.2/go.mod h1:sAlhrkVDf50ZHx6z4K0S40wISNTarf1r800F+RlCF6U= -k8s.io/code-generator v0.21.0/go.mod h1:hUlps5+9QaTrKx+jiM4rmq7YmH8wPOIko64uZCHDh6Q= -k8s.io/component-base v0.21.0 h1:tLLGp4BBjQaCpS/KiuWh7m2xqvAdsxLm4ATxHSe5Zpg= -k8s.io/component-base v0.21.0/go.mod h1:qvtjz6X0USWXbgmbfXR+Agik4RZ3jv2Bgr5QnZzdPYw= -k8s.io/component-helpers v0.21.0/go.mod h1:tezqefP7lxfvJyR+0a+6QtVrkZ/wIkyMLK4WcQ3Cj8U= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +k8s.io/api v0.24.2/go.mod h1:AHqbSkTm6YrQ0ObxjO3Pmp/ubFF/KuM7jU+3khoBsOg= +k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI= +k8s.io/api v0.25.0 h1:H+Q4ma2U/ww0iGB78ijZx6DRByPz6/733jIuFpX70e0= +k8s.io/api v0.25.0/go.mod h1:ttceV1GyV1i1rnmvzT3BST08N6nGt+dudGrquzVQWPk= +k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= +k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= +k8s.io/apimachinery v0.24.2/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM= +k8s.io/apimachinery v0.25.0 h1:MlP0r6+3XbkUG2itd6vp3oxbtdQLQI94fD5gCS+gnoU= +k8s.io/apimachinery v0.25.0/go.mod h1:qMx9eAk0sZQGsXGu86fab8tZdffHbwUfsvzqKn4mfB0= +k8s.io/apiserver v0.25.0 h1:8kl2ifbNffD440MyvHtPaIz1mw4mGKVgWqM0nL+oyu4= +k8s.io/apiserver v0.25.0/go.mod h1:BKwsE+PTC+aZK+6OJQDPr0v6uS91/HWxX7evElAH6xo= +k8s.io/cli-runtime v0.24.2/go.mod h1:1LIhKL2RblkhfG4v5lZEt7FtgFG5mVb8wqv5lE9m5qY= +k8s.io/cli-runtime v0.24.3 h1:O9YvUHrDSCQUPlsqVmaqDrueqjpJ7IO6Yas9B6xGSoo= +k8s.io/cli-runtime v0.24.3/go.mod h1:In84wauoMOqa7JDvDSXGbf8lTNlr70fOGpYlYfJtSqA= +k8s.io/client-go v0.24.2/go.mod h1:zg4Xaoo+umDsfCWr4fCnmLEtQXyCNXCvJuSsglNcV30= +k8s.io/client-go v0.24.3/go.mod h1:AAovolf5Z9bY1wIg2FZ8LPQlEdKHjLI7ZD4rw920BJw= +k8s.io/client-go v0.25.0 h1:CVWIaCETLMBNiTUta3d5nzRbXvY5Hy9Dpl+VvREpu5E= +k8s.io/client-go v0.25.0/go.mod h1:lxykvypVfKilxhTklov0wz1FoaUZ8X4EwbhS6rpRfN8= +k8s.io/code-generator v0.24.2/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w= +k8s.io/component-base v0.24.2/go.mod h1:ucHwW76dajvQ9B7+zecZAP3BVqvrHoOxm8olHEg0nmM= +k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y= +k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= +k8s.io/component-helpers v0.24.2/go.mod h1:TRQPBQKfmqkmV6c0HAmUs8cXVNYYYLsXy4zu8eODi9g= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM= -k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE= -k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM= +k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= +k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= +k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw= -k8s.io/kubectl v0.21.0 h1:WZXlnG/yjcE4LWO2g6ULjFxtzK6H1TKzsfaBFuVIhNg= -k8s.io/kubectl v0.21.0/go.mod h1:EU37NukZRXn1TpAkMUoy8Z/B2u6wjHDS4aInsDzVvks= -k8s.io/metrics v0.21.0/go.mod h1:L3Ji9EGPP1YBbfm9sPfEXSpnj8i24bfQbAFAsW0NueQ= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a h1:8dYfu/Fc9Gz2rNJKB9IQRGgQOh2clmRzNIPPY1xLY5g= -k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk= +k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= +k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= +k8s.io/kubectl v0.24.2 h1:+RfQVhth8akUmIc2Ge8krMl/pt66V7210ka3RE/p0J4= +k8s.io/kubectl v0.24.2/go.mod h1:+HIFJc0bA6Tzu5O/YcuUt45APAxnNL8LeMuXwoiGsPg= +k8s.io/metrics v0.24.2/go.mod h1:5NWURxZ6Lz5gj8TFU83+vdWIVASx7W8lwPpHYCqopMo= +k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= +k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +oras.land/oras-go v1.2.0 h1:yoKosVIbsPoFMqAIFHTnrmOuafHal+J/r+I5bdbVWu4= +oras.land/oras-go v1.2.0/go.mod h1:pFNs7oHp2dYsYMSS82HaX5l4mpnGO7hbpPN6EWH2ltc= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/letsencrypt v0.0.3 h1:H7xDfhkaFFSYEJlKeq38RwX2jYcnTeHuDQyT+mMNMwM= -rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= -sigs.k8s.io/kustomize/api v0.8.5 h1:bfCXGXDAbFbb/Jv5AhMj2BB8a5VAJuuQ5/KU69WtDjQ= -sigs.k8s.io/kustomize/api v0.8.5/go.mod h1:M377apnKT5ZHJS++6H4rQoCHmWtt6qTpp3mbe7p6OLY= -sigs.k8s.io/kustomize/cmd/config v0.9.7/go.mod h1:MvXCpHs77cfyxRmCNUQjIqCmZyYsbn5PyQpWiq44nW0= -sigs.k8s.io/kustomize/kustomize/v4 v4.0.5/go.mod h1:C7rYla7sI8EnxHE/xEhRBSHMNfcL91fx0uKmUlUhrBk= -sigs.k8s.io/kustomize/kyaml v0.10.15 h1:dSLgG78KyaxN4HylPXdK+7zB3k7sW6q3IcCmcfKA+aI= -sigs.k8s.io/kustomize/kyaml v0.10.15/go.mod h1:mlQFagmkm1P+W4lZJbJ/yaxMd8PqMRSC4cPcfUVt5Hg= +sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= +sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.11.4 h1:/0Mr3kfBBNcNPOW5Qwk/3eb8zkswCwnqQxxKtmrTkRo= +sigs.k8s.io/kustomize/api v0.11.4/go.mod h1:k+8RsqYbgpkIrJ4p9jcdPqe8DprLxFUUO0yNOq8C+xI= +sigs.k8s.io/kustomize/cmd/config v0.10.6/go.mod h1:/S4A4nUANUa4bZJ/Edt7ZQTyKOY9WCER0uBS1SW2Rco= +sigs.k8s.io/kustomize/kustomize/v4 v4.5.4/go.mod h1:Zo/Xc5FKD6sHl0lilbrieeGeZHVYCA4BzxeAaLI05Bg= +sigs.k8s.io/kustomize/kyaml v0.13.6 h1:eF+wsn4J7GOAXlvajv6OknSunxpcOBQQqsnPxObtkGs= +sigs.k8s.io/kustomize/kyaml v0.13.6/go.mod h1:yHP031rn1QX1lr/Xd934Ri/xdVNG8BE2ECa78Ht/kEg= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno= -sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= +sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= +sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= +sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= +sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/control-plane/Makefile b/control-plane/Makefile index 4c3cbac971..b6d6594c3d 100644 --- a/control-plane/Makefile +++ b/control-plane/Makefile @@ -22,8 +22,29 @@ CI_DEV_DOCKER_NAMESPACE?=hashicorpdev CI_DEV_DOCKER_IMAGE_NAME?=consul-k8s-control-plane CI_DEV_DOCKER_WORKDIR?=. CONSUL_K8S_IMAGE_VERSION?=latest + +# Helm Test Image +CI_DEV_HELM_TEST_IMAGE?=consul-helm-test +# Represent the latest supported version for this branch +# Increment this when building a new version container +TEST_IMAGE_VERSION=0.12.3 +HELM_TEST_WORKDIR=../charts/consul/test/docker + ################ +# Make target for building and pushing the helm test container +# used to run various pipeline tests (including GKE/AKS/EKS). This container +# provides the necessary dependencies for running on our cloud targets. +ci.dev-helm-test-docker: + @echo "Building helm test Development container - $(CI_DEV_HELM_TEST_IMAGE)" + @echo $(DOCKER_PASS) | docker login -u="$(DOCKER_USER)" --password-stdin + @docker buildx create --use && docker buildx build -t '$(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_HELM_TEST_IMAGE):$(TEST_IMAGE_VERSION)' \ + --platform linux/amd64,linux/arm64 \ + --push \ + --label COMMIT_SHA=$(GIT_COMMIT) \ + $(HELM_TEST_WORKDIR) -f $(HELM_TEST_WORKDIR)/Test.dockerfile + @echo "Pushed dev image to: $(CI_DEV_DOCKER_NAMESPACE)/$(CI_DEV_HELM_TEST_IMAGE):$(TEST_IMAGE_VERSION)" + # TODO: Remove this ci.dev-docker target once we move the acceptance tests to Github Actions. # In CircleCI, the linux binary will be attached from a previous step at pkg/bin/linux_amd64/. This make target # should only run in CI and not locally. From 53b64e1e0e947d9db8c3996570f998bba21534d4 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Thu, 10 Nov 2022 15:32:20 -0800 Subject: [PATCH 177/235] Backport of Add support for maxConnections, maxConcurrentRequests, and maxPendingRequests to IngressGateway CRD into release/0.49.x (#1700) * backport of commit 7592592167e6e8831d7dd56a3c5ffd55babf9a16 * backport of commit 876eb7c20e46e8aa5b88a37322dd7523c2a6dae2 * backport of commit 438aae1c90a6e87ab36301fd30975d4682d3d12a Co-authored-by: Semir Patel --- .../consul/templates/crd-ingressgateways.yaml | 22 +++ .../api/v1alpha1/ingressgateway_types.go | 76 ++++++++- .../api/v1alpha1/ingressgateway_types_test.go | 158 +++++++++++++++++- .../api/v1alpha1/zz_generated.deepcopy.go | 50 ++++++ .../consul.hashicorp.com_ingressgateways.yaml | 22 +++ 5 files changed, 313 insertions(+), 15 deletions(-) diff --git a/charts/consul/templates/crd-ingressgateways.yaml b/charts/consul/templates/crd-ingressgateways.yaml index f14789e83d..1a241a9cfb 100644 --- a/charts/consul/templates/crd-ingressgateways.yaml +++ b/charts/consul/templates/crd-ingressgateways.yaml @@ -57,6 +57,19 @@ spec: spec: description: IngressGatewaySpec defines the desired state of IngressGateway. properties: + defaults: + description: Defaults is default configuration for all upstream services + properties: + maxConcurrentRequests: + format: int32 + type: integer + maxConnections: + format: int32 + type: integer + maxPendingRequests: + format: int32 + type: integer + type: object listeners: description: Listeners declares what ports the ingress gateway should listen on, and what services to associated to those ports. @@ -98,6 +111,15 @@ spec: items: type: string type: array + maxConcurrentRequests: + format: int32 + type: integer + maxConnections: + format: int32 + type: integer + maxPendingRequests: + format: int32 + type: integer name: description: "Name declares the service to which traffic should be forwarded. \n This can either be a specific diff --git a/control-plane/api/v1alpha1/ingressgateway_types.go b/control-plane/api/v1alpha1/ingressgateway_types.go index 7251608223..d213b7eb84 100644 --- a/control-plane/api/v1alpha1/ingressgateway_types.go +++ b/control-plane/api/v1alpha1/ingressgateway_types.go @@ -57,6 +57,15 @@ type IngressGatewaySpec struct { // Listeners declares what ports the ingress gateway should listen on, and // what services to associated to those ports. Listeners []IngressListener `json:"listeners,omitempty"` + + // Defaults is default configuration for all upstream services + Defaults *IngressServiceConfig `json:"defaults,omitempty"` +} + +type IngressServiceConfig struct { + MaxConnections *uint32 `json:"maxConnections,omitempty"` + MaxPendingRequests *uint32 `json:"maxPendingRequests,omitempty"` + MaxConcurrentRequests *uint32 `json:"maxConcurrentRequests,omitempty"` } type GatewayTLSConfig struct { @@ -144,6 +153,10 @@ type IngressService struct { // Allow HTTP header manipulation to be configured. RequestHeaders *HTTPHeaderModifiers `json:"requestHeaders,omitempty"` ResponseHeaders *HTTPHeaderModifiers `json:"responseHeaders,omitempty"` + + MaxConnections *uint32 `json:"maxConnections,omitempty"` + MaxPendingRequests *uint32 `json:"maxPendingRequests,omitempty"` + MaxConcurrentRequests *uint32 `json:"maxConcurrentRequests,omitempty"` } func (in *IngressGateway) GetObjectMeta() metav1.ObjectMeta { @@ -235,6 +248,7 @@ func (in *IngressGateway) ToConsul(datacenter string) capi.ConfigEntry { TLS: *in.Spec.TLS.toConsul(), Listeners: listeners, Meta: meta(datacenter), + Defaults: in.Spec.Defaults.toConsul(), } } @@ -257,6 +271,8 @@ func (in *IngressGateway) Validate(consulMeta common.ConsulMeta) error { errs = append(errs, v.validate(path.Child("listeners").Index(i), consulMeta)...) } + errs = append(errs, in.Spec.Defaults.validate(path.Child("defaults"))...) + if len(errs) > 0 { return apierrors.NewInvalid( schema.GroupKind{Group: ConsulHashicorpGroup, Kind: ingressGatewayKubeKind}, @@ -329,13 +345,16 @@ func (in IngressListener) toConsul() capi.IngressListener { func (in IngressService) toConsul() capi.IngressService { return capi.IngressService{ - Name: in.Name, - Hosts: in.Hosts, - Namespace: in.Namespace, - Partition: in.Partition, - TLS: in.TLS.toConsul(), - RequestHeaders: in.RequestHeaders.toConsul(), - ResponseHeaders: in.ResponseHeaders.toConsul(), + Name: in.Name, + Hosts: in.Hosts, + Namespace: in.Namespace, + Partition: in.Partition, + TLS: in.TLS.toConsul(), + RequestHeaders: in.RequestHeaders.toConsul(), + ResponseHeaders: in.ResponseHeaders.toConsul(), + MaxConnections: in.MaxConnections, + MaxPendingRequests: in.MaxPendingRequests, + MaxConcurrentRequests: in.MaxConcurrentRequests, } } @@ -406,6 +425,49 @@ func (in IngressListener) validate(path *field.Path, consulMeta common.ConsulMet string(asJSON), "hosts must be empty if protocol is \"tcp\"")) } + + if svc.MaxConnections != nil && *svc.MaxConnections <= 0 { + errs = append(errs, field.Invalid(path.Child("maxconnections"), *svc.MaxConnections, "MaxConnections must be > 0")) + } + + if svc.MaxConcurrentRequests != nil && *svc.MaxConcurrentRequests <= 0 { + errs = append(errs, field.Invalid(path.Child("maxconcurrentrequests"), *svc.MaxConcurrentRequests, "MaxConcurrentRequests must be > 0")) + } + + if svc.MaxPendingRequests != nil && *svc.MaxPendingRequests <= 0 { + errs = append(errs, field.Invalid(path.Child("maxpendingrequests"), *svc.MaxPendingRequests, "MaxPendingRequests must be > 0")) + } + } + return errs +} + +func (in *IngressServiceConfig) validate(path *field.Path) field.ErrorList { + if in == nil { + return nil + } + var errs field.ErrorList + + if in.MaxConnections != nil && *in.MaxConnections <= 0 { + errs = append(errs, field.Invalid(path.Child("maxconnections"), *in.MaxConnections, "MaxConnections must be > 0")) + } + + if in.MaxConcurrentRequests != nil && *in.MaxConcurrentRequests <= 0 { + errs = append(errs, field.Invalid(path.Child("maxconcurrentrequests"), *in.MaxConcurrentRequests, "MaxConcurrentRequests must be > 0")) + } + + if in.MaxPendingRequests != nil && *in.MaxPendingRequests <= 0 { + errs = append(errs, field.Invalid(path.Child("maxpendingrequests"), *in.MaxPendingRequests, "MaxPendingRequests must be > 0")) } return errs } + +func (in *IngressServiceConfig) toConsul() *capi.IngressServiceConfig { + if in == nil { + return nil + } + return &capi.IngressServiceConfig{ + MaxConnections: in.MaxConnections, + MaxPendingRequests: in.MaxPendingRequests, + MaxConcurrentRequests: in.MaxConcurrentRequests, + } +} diff --git a/control-plane/api/v1alpha1/ingressgateway_types_test.go b/control-plane/api/v1alpha1/ingressgateway_types_test.go index 2585614519..c60f487954 100644 --- a/control-plane/api/v1alpha1/ingressgateway_types_test.go +++ b/control-plane/api/v1alpha1/ingressgateway_types_test.go @@ -253,6 +253,15 @@ func TestIngressGateway_MatchesConsul(t *testing.T) { } func TestIngressGateway_ToConsul(t *testing.T) { + + defaultMaxConnections := uint32(100) + defaultMaxPendingRequests := uint32(101) + defaultMaxConcurrentRequests := uint32(102) + + maxConnections := uint32(200) + maxPendingRequests := uint32(201) + maxConcurrentRequests := uint32(202) + cases := map[string]struct { Ours IngressGateway Exp *capi.IngressGatewayConfigEntry @@ -289,6 +298,11 @@ func TestIngressGateway_ToConsul(t *testing.T) { TLSMaxVersion: "TLSv1_1", CipherSuites: []string{"ECDHE-ECDSA-AES128-GCM-SHA256", "AES128-SHA"}, }, + Defaults: &IngressServiceConfig{ + MaxConnections: &defaultMaxConnections, + MaxPendingRequests: &defaultMaxPendingRequests, + MaxConcurrentRequests: &defaultMaxConcurrentRequests, + }, Listeners: []IngressListener{ { Port: 8888, @@ -305,10 +319,13 @@ func TestIngressGateway_ToConsul(t *testing.T) { }, Services: []IngressService{ { - Name: "name1", - Hosts: []string{"host1_1", "host1_2"}, - Namespace: "ns1", - Partition: "default", + Name: "name1", + Hosts: []string{"host1_1", "host1_2"}, + Namespace: "ns1", + Partition: "default", + MaxConnections: &maxConnections, + MaxPendingRequests: &maxPendingRequests, + MaxConcurrentRequests: &maxConcurrentRequests, TLS: &GatewayServiceTLSConfig{ SDS: &GatewayTLSSDSConfig{ ClusterName: "cluster1", @@ -378,6 +395,11 @@ func TestIngressGateway_ToConsul(t *testing.T) { TLSMaxVersion: "TLSv1_1", CipherSuites: []string{"ECDHE-ECDSA-AES128-GCM-SHA256", "AES128-SHA"}, }, + Defaults: &capi.IngressServiceConfig{ + MaxConnections: &defaultMaxConnections, + MaxPendingRequests: &defaultMaxPendingRequests, + MaxConcurrentRequests: &defaultMaxConcurrentRequests, + }, Listeners: []capi.IngressListener{ { Port: 8888, @@ -394,10 +416,13 @@ func TestIngressGateway_ToConsul(t *testing.T) { }, Services: []capi.IngressService{ { - Name: "name1", - Hosts: []string{"host1_1", "host1_2"}, - Namespace: "ns1", - Partition: "default", + Name: "name1", + Hosts: []string{"host1_1", "host1_2"}, + Namespace: "ns1", + Partition: "default", + MaxConnections: &maxConnections, + MaxPendingRequests: &maxPendingRequests, + MaxConcurrentRequests: &maxConcurrentRequests, TLS: &capi.GatewayServiceTLSConfig{ SDS: &capi.GatewayTLSSDSConfig{ ClusterName: "cluster1", @@ -471,6 +496,8 @@ func TestIngressGateway_ToConsul(t *testing.T) { } func TestIngressGateway_Validate(t *testing.T) { + zero := uint32(0) + cases := map[string]struct { input *IngressGateway namespacesEnabled bool @@ -785,6 +812,121 @@ func TestIngressGateway_Validate(t *testing.T) { }, partitionEnabled: true, }, + "defaults.maxConnections invalid": { + input: &IngressGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + Spec: IngressGatewaySpec{ + Defaults: &IngressServiceConfig{ + MaxConnections: &zero, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.defaults.maxconnections: Invalid`, + }, + }, + "defaults.maxPendingRequests invalid": { + input: &IngressGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + Spec: IngressGatewaySpec{ + Defaults: &IngressServiceConfig{ + MaxPendingRequests: &zero, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.defaults.maxpendingrequests: Invalid`, + }, + }, + "defaults.maxConcurrentRequests invalid": { + input: &IngressGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + Spec: IngressGatewaySpec{ + Defaults: &IngressServiceConfig{ + MaxConcurrentRequests: &zero, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.defaults.maxconcurrentrequests: Invalid`, + }, + }, + "service.maxConnections invalid": { + input: &IngressGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + Spec: IngressGatewaySpec{ + Listeners: []IngressListener{ + { + Protocol: "http", + Services: []IngressService{ + { + Name: "svc1", + MaxConnections: &zero, + }, + }, + }, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.listeners[0].maxconnections: Invalid`, + }, + }, + "service.maxConcurrentRequests invalid": { + input: &IngressGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + Spec: IngressGatewaySpec{ + Listeners: []IngressListener{ + { + Protocol: "http", + Services: []IngressService{ + { + Name: "svc1", + MaxConcurrentRequests: &zero, + }, + }, + }, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.listeners[0].maxconcurrentrequests: Invalid`, + }, + }, + "service.maxPendingRequests invalid": { + input: &IngressGateway{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + }, + Spec: IngressGatewaySpec{ + Listeners: []IngressListener{ + { + Protocol: "http", + Services: []IngressService{ + { + Name: "svc1", + MaxPendingRequests: &zero, + }, + }, + }, + }, + }, + }, + expectedErrMsgs: []string{ + `spec.listeners[0].maxpendingrequests: Invalid`, + }, + }, + "multiple errors": { input: &IngressGateway{ ObjectMeta: metav1.ObjectMeta{ diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index 85d64c3c85..af7ec840a1 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -383,6 +383,11 @@ func (in *IngressGatewaySpec) DeepCopyInto(out *IngressGatewaySpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Defaults != nil { + in, out := &in.Defaults, &out.Defaults + *out = new(IngressServiceConfig) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressGatewaySpec. @@ -445,6 +450,21 @@ func (in *IngressService) DeepCopyInto(out *IngressService) { *out = new(HTTPHeaderModifiers) (*in).DeepCopyInto(*out) } + if in.MaxConnections != nil { + in, out := &in.MaxConnections, &out.MaxConnections + *out = new(uint32) + **out = **in + } + if in.MaxPendingRequests != nil { + in, out := &in.MaxPendingRequests, &out.MaxPendingRequests + *out = new(uint32) + **out = **in + } + if in.MaxConcurrentRequests != nil { + in, out := &in.MaxConcurrentRequests, &out.MaxConcurrentRequests + *out = new(uint32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressService. @@ -457,6 +477,36 @@ func (in *IngressService) DeepCopy() *IngressService { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IngressServiceConfig) DeepCopyInto(out *IngressServiceConfig) { + *out = *in + if in.MaxConnections != nil { + in, out := &in.MaxConnections, &out.MaxConnections + *out = new(uint32) + **out = **in + } + if in.MaxPendingRequests != nil { + in, out := &in.MaxPendingRequests, &out.MaxPendingRequests + *out = new(uint32) + **out = **in + } + if in.MaxConcurrentRequests != nil { + in, out := &in.MaxConcurrentRequests, &out.MaxConcurrentRequests + *out = new(uint32) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressServiceConfig. +func (in *IngressServiceConfig) DeepCopy() *IngressServiceConfig { + if in == nil { + return nil + } + out := new(IngressServiceConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *IntentionDestination) DeepCopyInto(out *IntentionDestination) { *out = *in diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml index 6378ee4213..9934e9c0d9 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml @@ -50,6 +50,19 @@ spec: spec: description: IngressGatewaySpec defines the desired state of IngressGateway. properties: + defaults: + description: Defaults is default configuration for all upstream services + properties: + maxConcurrentRequests: + format: int32 + type: integer + maxConnections: + format: int32 + type: integer + maxPendingRequests: + format: int32 + type: integer + type: object listeners: description: Listeners declares what ports the ingress gateway should listen on, and what services to associated to those ports. @@ -91,6 +104,15 @@ spec: items: type: string type: array + maxConcurrentRequests: + format: int32 + type: integer + maxConnections: + format: int32 + type: integer + maxPendingRequests: + format: int32 + type: integer name: description: "Name declares the service to which traffic should be forwarded. \n This can either be a specific From 4f14a735d7aea27f4fcfbc21c14b5b73079ecf7d Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 14 Nov 2022 08:56:23 -0700 Subject: [PATCH 178/235] peering: update exported services CRD and bump api module (#1596) (#1705) Co-authored-by: Nitya Dhanushkodi --- .../api/v1alpha1/exportedservices_types.go | 2 +- .../v1alpha1/exportedservices_types_test.go | 8 ++++---- .../peering_dialer_controller_test.go | 7 +++++++ control-plane/go.mod | 8 +++++--- control-plane/go.sum | 20 +++++++++---------- 5 files changed, 27 insertions(+), 18 deletions(-) diff --git a/control-plane/api/v1alpha1/exportedservices_types.go b/control-plane/api/v1alpha1/exportedservices_types.go index 3087379c62..e05f17a177 100644 --- a/control-plane/api/v1alpha1/exportedservices_types.go +++ b/control-plane/api/v1alpha1/exportedservices_types.go @@ -167,7 +167,7 @@ func (in *ExportedService) toConsul() capi.ExportedService { for _, consumer := range in.Consumers { consumers = append(consumers, capi.ServiceConsumer{ Partition: consumer.Partition, - PeerName: consumer.Peer, + Peer: consumer.Peer, }) } return capi.ExportedService{ diff --git a/control-plane/api/v1alpha1/exportedservices_types_test.go b/control-plane/api/v1alpha1/exportedservices_types_test.go index 0810f8edaf..8826166a76 100644 --- a/control-plane/api/v1alpha1/exportedservices_types_test.go +++ b/control-plane/api/v1alpha1/exportedservices_types_test.go @@ -90,7 +90,7 @@ func TestExportedServices_MatchesConsul(t *testing.T) { Partition: "third", }, { - PeerName: "second-peer", + Peer: "second-peer", }, }, }, @@ -105,7 +105,7 @@ func TestExportedServices_MatchesConsul(t *testing.T) { Partition: "fifth", }, { - PeerName: "third-peer", + Peer: "third-peer", }, }, }, @@ -214,7 +214,7 @@ func TestExportedServices_ToConsul(t *testing.T) { Partition: "third", }, { - PeerName: "second-peer", + Peer: "second-peer", }, }, }, @@ -229,7 +229,7 @@ func TestExportedServices_ToConsul(t *testing.T) { Partition: "fifth", }, { - PeerName: "third-peer", + Peer: "third-peer", }, }, }, diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index 120618eafd..70076c75ec 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -251,6 +251,10 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { // Create test consul server. acceptorPeerServer, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) { c.NodeName = nodeName + // We set the datacenter because the server name, typically formatted as "server.." + // must be unique on the acceptor and dialer peers. Otherwise the following consul error will be thrown: + // https://github.com/hashicorp/consul/blob/74b87d49d33069a048aead7a86d85d4b4b6461b5/agent/rpc/peering/service.go#L491. + c.Datacenter = "acceptor-dc" }) require.NoError(t, err) defer acceptorPeerServer.Stop() @@ -431,6 +435,9 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { // Create test consul server. acceptorPeerServer, err := testutil.NewTestServerConfigT(t, func(c *testutil.TestServerConfig) { c.NodeName = nodeName + // We set the datacenter because the server name, typically formatted as "server.." + // must be unique on the acceptor and dialer peers. + c.Datacenter = "acceptor-dc" }) require.NoError(t, err) defer acceptorPeerServer.Stop() diff --git a/control-plane/go.mod b/control-plane/go.mod index 8d0f894729..d3c6106eac 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -9,12 +9,14 @@ require ( github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 - github.com/hashicorp/consul/api v1.10.1-0.20220913205944-e743eefbd104 + github.com/hashicorp/consul-server-connection-manager v0.0.0-20220922180412-01c5be1c636f + github.com/hashicorp/consul/api v1.10.1-0.20221005170644-13da2c5fad69 github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f github.com/hashicorp/go-hclog v1.2.2 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/serf v0.9.7 + github.com/hashicorp/go-rootcerts v1.0.2 + github.com/hashicorp/serf v0.10.1 github.com/kr/text v0.2.0 github.com/miekg/dns v1.1.41 github.com/mitchellh/cli v1.1.0 @@ -110,7 +112,7 @@ require ( golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d // indirect + golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/api v0.43.0 // indirect diff --git a/control-plane/go.sum b/control-plane/go.sum index 00ee1f4970..f281ffad23 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -342,10 +342,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFb github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 h1:TQY0oKtLV15UNYWeSkTxi4McBIyLecsEtbc/VfxvbYA= github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8/go.mod h1:aw35GB76URgbtxaSSMxbOetbG7YEHHPkIX3/SkTBaWc= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.10.1-0.20220913205944-e743eefbd104 h1:NW0jZq0suX2gfHVFmKuJ5DGLXSP7qN9FmjQOU764fFQ= -github.com/hashicorp/consul/api v1.10.1-0.20220913205944-e743eefbd104/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ= +github.com/hashicorp/consul/api v1.10.1-0.20221005170644-13da2c5fad69 h1:IALuDSO0f6x0txq/tjUDF3sShyDMT8dmjn9af6Ik8BA= +github.com/hashicorp/consul/api v1.10.1-0.20221005170644-13da2c5fad69/go.mod h1:T09kWtKqm8j1S9yTd1r0hVhfOyPrvLb0zb6dPKpNXxQ= +github.com/hashicorp/consul/proto-public v0.1.0 h1:O0LSmCqydZi363hsqc6n2v5sMz3usQMXZF6ziK3SzXU= +github.com/hashicorp/consul/proto-public v0.1.0/go.mod h1:vs2KkuWwtjkIgA5ezp4YKPzQp4GitV+q/+PvksrA92k= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= @@ -394,12 +395,11 @@ github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg github.com/hashicorp/mdns v1.0.4 h1:sY0CMhFmjIPDMlTB+HfymFHCaYLhgifZ0QhjaYKD/UQ= github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= -github.com/hashicorp/memberlist v0.3.1 h1:MXgUXLqva1QvpVEDQW1IQLG0wivQAtmFlHRQ+1vWZfM= -github.com/hashicorp/memberlist v0.3.1/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/memberlist v0.5.0 h1:EtYPN8DpAURiapus508I4n9CzHs2W+8NZGbmmR/prTM= +github.com/hashicorp/memberlist v0.5.0/go.mod h1:yvyXLpo0QaGE59Y7hDTsTzDD25JYBZ4mHgHUZ8lrOI0= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/serf v0.9.7 h1:hkdgbqizGQHuU5IPqYM1JdSMV8nKfpuOnZYXssk9muY= -github.com/hashicorp/serf v0.9.7/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= +github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= +github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443 h1:O/pT5C1Q3mVXMyuqg7yuAWUg/jMZR1/0QTzTRdNR6Uw= github.com/hashicorp/vic v1.5.1-0.20190403131502-bbfe86ec9443/go.mod h1:bEpDU35nTu0ey1EXjwNwPjI9xErAsoOCmcMb9GKvyxo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -900,8 +900,8 @@ golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d h1:/m5NbqQelATgoSPVC2Z23sR4kVNokFwDDyWh/3rGY+I= -golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= +golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From c4ec2cfe825f90477bee71e1b7e280866cd8631b Mon Sep 17 00:00:00 2001 From: John Murret Date: Mon, 14 Nov 2022 10:28:05 -0700 Subject: [PATCH 179/235] Add support for maxConnections, maxConcurrentRequests, and maxPendingRequests to IngressGateway CRD (#1691) (#1706) Co-authored-by: Semir Patel --- CHANGELOG.md | 3 + .../consul/templates/crd-ingressgateways.yaml | 19 +++++ .../api/v1alpha1/ingressgateway_types.go | 28 ++++---- .../api/v1alpha1/ingressgateway_types_test.go | 69 ++++++++++++++----- .../api/v1alpha1/zz_generated.deepcopy.go | 16 +---- .../consul.hashicorp.com_ingressgateways.yaml | 19 +++++ 6 files changed, 106 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ce8d8aca5..71c37d205a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## UNRELEASED +FEATURES: +* Ingress Gateway + * Add support for MaxConnections, MaxConcurrentRequests, and MaxPendingRequests to Ingress Gateway CRD. [[GH-1691](https://github.com/hashicorp/consul-k8s/pull/1691)] IMPROVEMENTS: * Helm: diff --git a/charts/consul/templates/crd-ingressgateways.yaml b/charts/consul/templates/crd-ingressgateways.yaml index 1a241a9cfb..6aeca4a2f7 100644 --- a/charts/consul/templates/crd-ingressgateways.yaml +++ b/charts/consul/templates/crd-ingressgateways.yaml @@ -61,12 +61,21 @@ spec: description: Defaults is default configuration for all upstream services properties: maxConcurrentRequests: + description: The maximum number of concurrent requests that will + be allowed at a single point in time. Use this to limit HTTP/2 + traffic, since HTTP/2 has many requests per connection. format: int32 type: integer maxConnections: + description: The maximum number of connections a service instance + will be allowed to establish against the given upstream. Use + this to limit HTTP/1.1 traffic, since HTTP/1.1 has a request + per connection. format: int32 type: integer maxPendingRequests: + description: The maximum number of requests that will be queued + while waiting for a connection to be established. format: int32 type: integer type: object @@ -112,12 +121,22 @@ spec: type: string type: array maxConcurrentRequests: + description: The maximum number of concurrent requests + that will be allowed at a single point in time. Use + this to limit HTTP/2 traffic, since HTTP/2 has many + requests per connection. format: int32 type: integer maxConnections: + description: The maximum number of connections a service + instance will be allowed to establish against the given + upstream. Use this to limit HTTP/1.1 traffic, since + HTTP/1.1 has a request per connection. format: int32 type: integer maxPendingRequests: + description: The maximum number of requests that will + be queued while waiting for a connection to be established. format: int32 type: integer name: diff --git a/control-plane/api/v1alpha1/ingressgateway_types.go b/control-plane/api/v1alpha1/ingressgateway_types.go index d213b7eb84..c94b6e1458 100644 --- a/control-plane/api/v1alpha1/ingressgateway_types.go +++ b/control-plane/api/v1alpha1/ingressgateway_types.go @@ -63,8 +63,16 @@ type IngressGatewaySpec struct { } type IngressServiceConfig struct { - MaxConnections *uint32 `json:"maxConnections,omitempty"` - MaxPendingRequests *uint32 `json:"maxPendingRequests,omitempty"` + // The maximum number of connections a service instance + // will be allowed to establish against the given upstream. Use this to limit + // HTTP/1.1 traffic, since HTTP/1.1 has a request per connection. + MaxConnections *uint32 `json:"maxConnections,omitempty"` + // The maximum number of requests that will be queued + // while waiting for a connection to be established. + MaxPendingRequests *uint32 `json:"maxPendingRequests,omitempty"` + // The maximum number of concurrent requests that + // will be allowed at a single point in time. Use this to limit HTTP/2 traffic, + // since HTTP/2 has many requests per connection. MaxConcurrentRequests *uint32 `json:"maxConcurrentRequests,omitempty"` } @@ -154,9 +162,7 @@ type IngressService struct { RequestHeaders *HTTPHeaderModifiers `json:"requestHeaders,omitempty"` ResponseHeaders *HTTPHeaderModifiers `json:"responseHeaders,omitempty"` - MaxConnections *uint32 `json:"maxConnections,omitempty"` - MaxPendingRequests *uint32 `json:"maxPendingRequests,omitempty"` - MaxConcurrentRequests *uint32 `json:"maxConcurrentRequests,omitempty"` + IngressServiceConfig `json:",inline"` } func (in *IngressGateway) GetObjectMeta() metav1.ObjectMeta { @@ -426,17 +432,7 @@ func (in IngressListener) validate(path *field.Path, consulMeta common.ConsulMet "hosts must be empty if protocol is \"tcp\"")) } - if svc.MaxConnections != nil && *svc.MaxConnections <= 0 { - errs = append(errs, field.Invalid(path.Child("maxconnections"), *svc.MaxConnections, "MaxConnections must be > 0")) - } - - if svc.MaxConcurrentRequests != nil && *svc.MaxConcurrentRequests <= 0 { - errs = append(errs, field.Invalid(path.Child("maxconcurrentrequests"), *svc.MaxConcurrentRequests, "MaxConcurrentRequests must be > 0")) - } - - if svc.MaxPendingRequests != nil && *svc.MaxPendingRequests <= 0 { - errs = append(errs, field.Invalid(path.Child("maxpendingrequests"), *svc.MaxPendingRequests, "MaxPendingRequests must be > 0")) - } + errs = append(errs, svc.IngressServiceConfig.validate(path)...) } return errs } diff --git a/control-plane/api/v1alpha1/ingressgateway_types_test.go b/control-plane/api/v1alpha1/ingressgateway_types_test.go index c60f487954..4942d38e11 100644 --- a/control-plane/api/v1alpha1/ingressgateway_types_test.go +++ b/control-plane/api/v1alpha1/ingressgateway_types_test.go @@ -13,6 +13,15 @@ import ( ) func TestIngressGateway_MatchesConsul(t *testing.T) { + + defaultMaxConnections := uint32(100) + defaultMaxPendingRequests := uint32(101) + defaultMaxConcurrentRequests := uint32(102) + + maxConnections := uint32(200) + maxPendingRequests := uint32(201) + maxConcurrentRequests := uint32(202) + cases := map[string]struct { Ours IngressGateway Theirs capi.ConfigEntry @@ -54,6 +63,11 @@ func TestIngressGateway_MatchesConsul(t *testing.T) { TLSMaxVersion: "TLSv1_1", CipherSuites: []string{"ECDHE-ECDSA-AES128-GCM-SHA256", "AES128-SHA"}, }, + Defaults: &IngressServiceConfig{ + MaxConnections: &defaultMaxConnections, + MaxPendingRequests: &defaultMaxPendingRequests, + MaxConcurrentRequests: &defaultMaxConcurrentRequests, + }, Listeners: []IngressListener{ { Port: 8888, @@ -74,6 +88,11 @@ func TestIngressGateway_MatchesConsul(t *testing.T) { Hosts: []string{"host1_1", "host1_2"}, Namespace: "ns1", Partition: "default", + IngressServiceConfig: IngressServiceConfig{ + MaxConnections: &maxConnections, + MaxPendingRequests: &maxPendingRequests, + MaxConcurrentRequests: &maxConcurrentRequests, + }, TLS: &GatewayServiceTLSConfig{ SDS: &GatewayTLSSDSConfig{ ClusterName: "cluster1", @@ -144,6 +163,11 @@ func TestIngressGateway_MatchesConsul(t *testing.T) { TLSMaxVersion: "TLSv1_1", CipherSuites: []string{"ECDHE-ECDSA-AES128-GCM-SHA256", "AES128-SHA"}, }, + Defaults: &capi.IngressServiceConfig{ + MaxConnections: &defaultMaxConnections, + MaxPendingRequests: &defaultMaxPendingRequests, + MaxConcurrentRequests: &defaultMaxConcurrentRequests, + }, Listeners: []capi.IngressListener{ { Port: 8888, @@ -160,10 +184,13 @@ func TestIngressGateway_MatchesConsul(t *testing.T) { }, Services: []capi.IngressService{ { - Name: "name1", - Hosts: []string{"host1_1", "host1_2"}, - Namespace: "ns1", - Partition: "default", + Name: "name1", + Hosts: []string{"host1_1", "host1_2"}, + Namespace: "ns1", + Partition: "default", + MaxConnections: &maxConnections, + MaxPendingRequests: &maxPendingRequests, + MaxConcurrentRequests: &maxConcurrentRequests, TLS: &capi.GatewayServiceTLSConfig{ SDS: &capi.GatewayTLSSDSConfig{ ClusterName: "cluster1", @@ -319,13 +346,15 @@ func TestIngressGateway_ToConsul(t *testing.T) { }, Services: []IngressService{ { - Name: "name1", - Hosts: []string{"host1_1", "host1_2"}, - Namespace: "ns1", - Partition: "default", - MaxConnections: &maxConnections, - MaxPendingRequests: &maxPendingRequests, - MaxConcurrentRequests: &maxConcurrentRequests, + Name: "name1", + Hosts: []string{"host1_1", "host1_2"}, + Namespace: "ns1", + Partition: "default", + IngressServiceConfig: IngressServiceConfig{ + MaxConnections: &maxConnections, + MaxPendingRequests: &maxPendingRequests, + MaxConcurrentRequests: &maxConcurrentRequests, + }, TLS: &GatewayServiceTLSConfig{ SDS: &GatewayTLSSDSConfig{ ClusterName: "cluster1", @@ -868,8 +897,10 @@ func TestIngressGateway_Validate(t *testing.T) { Protocol: "http", Services: []IngressService{ { - Name: "svc1", - MaxConnections: &zero, + Name: "svc1", + IngressServiceConfig: IngressServiceConfig{ + MaxConnections: &zero, + }, }, }, }, @@ -891,8 +922,10 @@ func TestIngressGateway_Validate(t *testing.T) { Protocol: "http", Services: []IngressService{ { - Name: "svc1", - MaxConcurrentRequests: &zero, + Name: "svc1", + IngressServiceConfig: IngressServiceConfig{ + MaxConcurrentRequests: &zero, + }, }, }, }, @@ -914,8 +947,10 @@ func TestIngressGateway_Validate(t *testing.T) { Protocol: "http", Services: []IngressService{ { - Name: "svc1", - MaxPendingRequests: &zero, + Name: "svc1", + IngressServiceConfig: IngressServiceConfig{ + MaxPendingRequests: &zero, + }, }, }, }, diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index af7ec840a1..cacef8c64c 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -450,21 +450,7 @@ func (in *IngressService) DeepCopyInto(out *IngressService) { *out = new(HTTPHeaderModifiers) (*in).DeepCopyInto(*out) } - if in.MaxConnections != nil { - in, out := &in.MaxConnections, &out.MaxConnections - *out = new(uint32) - **out = **in - } - if in.MaxPendingRequests != nil { - in, out := &in.MaxPendingRequests, &out.MaxPendingRequests - *out = new(uint32) - **out = **in - } - if in.MaxConcurrentRequests != nil { - in, out := &in.MaxConcurrentRequests, &out.MaxConcurrentRequests - *out = new(uint32) - **out = **in - } + in.IngressServiceConfig.DeepCopyInto(&out.IngressServiceConfig) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IngressService. diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml index 9934e9c0d9..16ac322090 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_ingressgateways.yaml @@ -54,12 +54,21 @@ spec: description: Defaults is default configuration for all upstream services properties: maxConcurrentRequests: + description: The maximum number of concurrent requests that will + be allowed at a single point in time. Use this to limit HTTP/2 + traffic, since HTTP/2 has many requests per connection. format: int32 type: integer maxConnections: + description: The maximum number of connections a service instance + will be allowed to establish against the given upstream. Use + this to limit HTTP/1.1 traffic, since HTTP/1.1 has a request + per connection. format: int32 type: integer maxPendingRequests: + description: The maximum number of requests that will be queued + while waiting for a connection to be established. format: int32 type: integer type: object @@ -105,12 +114,22 @@ spec: type: string type: array maxConcurrentRequests: + description: The maximum number of concurrent requests + that will be allowed at a single point in time. Use + this to limit HTTP/2 traffic, since HTTP/2 has many + requests per connection. format: int32 type: integer maxConnections: + description: The maximum number of connections a service + instance will be allowed to establish against the given + upstream. Use this to limit HTTP/1.1 traffic, since + HTTP/1.1 has a request per connection. format: int32 type: integer maxPendingRequests: + description: The maximum number of requests that will + be queued while waiting for a connection to be established. format: int32 type: integer name: From 312fe00e8a336daf820a9d60e5c7b1d9196dd503 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Mon, 14 Nov 2022 12:34:50 -0800 Subject: [PATCH 180/235] add missing changelog from backport (#1713) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71c37d205a..504d7162b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,8 @@ ## UNRELEASED +BREAKING CHANGES: +* Peering: + * Rename `PeerName` to `Peer` in ExportedServices CRD. [[GH-1596](https://github.com/hashicorp/consul-k8s/pull/1596)] + FEATURES: * Ingress Gateway * Add support for MaxConnections, MaxConcurrentRequests, and MaxPendingRequests to Ingress Gateway CRD. [[GH-1691](https://github.com/hashicorp/consul-k8s/pull/1691)] From b983ab043947dc2fa1b889bf58167c4ec0ea260a Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Tue, 15 Nov 2022 12:11:40 -0800 Subject: [PATCH 181/235] release: bump consul image to 1.13.3 (#1715) * bump consul image to 1.13.3 and run make prepare-release * unit test with 1.13.3 * fix unit tests with consul 1.13.3 (#1720) --- .github/workflows/test.yml | 4 ++-- CHANGELOG.md | 2 +- charts/consul/Chart.yaml | 8 ++++---- charts/consul/values.yaml | 4 ++-- cli/version/version.go | 2 +- .../connect-inject/endpoints_controller_test.go | 12 ++++++------ .../connect-inject/peering_dialer_controller_test.go | 2 ++ control-plane/version/version.go | 2 +- 8 files changed, 19 insertions(+), 17 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ce1033a540..2196868c94 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,8 +4,8 @@ on: env: TEST_RESULTS: /tmp/test-results # path to where test results are saved - CONSUL_VERSION: 1.13.1 # Consul's OSS version to use in tests - CONSUL_ENT_VERSION: 1.13.1+ent # Consul's enterprise version to use in tests + CONSUL_VERSION: 1.13.3 # Consul's OSS version to use in tests + CONSUL_ENT_VERSION: 1.13.3+ent # Consul's enterprise version to use in tests GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. jobs: diff --git a/CHANGELOG.md b/CHANGELOG.md index 504d7162b9..33a8d51fd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.49.1 (November 14, 2022) BREAKING CHANGES: * Peering: * Rename `PeerName` to `Peer` in ExportedServices CRD. [[GH-1596](https://github.com/hashicorp/consul-k8s/pull/1596)] diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 8b7e2da587..a85b87ccfd 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul -version: 0.49.0 -appVersion: 1.13.2 +version: 0.49.1 +appVersion: 1.13.3 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -13,9 +13,9 @@ annotations: artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.13.2 + image: hashicorp/consul:1.13.3 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.0 + image: hashicorp/consul-k8s-control-plane:0.49.1 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 564de43780..7bf0c772c7 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -109,7 +109,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.13.2" + image: "hashicorp/consul:1.13.3" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.0 + imageK8S: hashicorp/consul-k8s-control-plane:0.49.1 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 082ffeb1f3..4f0607732d 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,7 +14,7 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.0" + Version = "0.49.1" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release diff --git a/control-plane/connect-inject/endpoints_controller_test.go b/control-plane/connect-inject/endpoints_controller_test.go index abbad4b2a6..49ee67a91d 100644 --- a/control-plane/connect-inject/endpoints_controller_test.go +++ b/control-plane/connect-inject/endpoints_controller_test.go @@ -435,7 +435,7 @@ func TestProcessUpstreams(t *testing.T) { }, expErr: "upstream \"upstream1:1234:dc1\" is invalid: ProxyDefaults mesh gateway mode is neither \"local\" nor \"remote\"", configEntry: func() api.ConfigEntry { - ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "pd") + ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "global") pd := ce.(*api.ProxyConfigEntry) pd.MeshGateway.Mode = "bad-mode" return pd @@ -492,7 +492,7 @@ func TestProcessUpstreams(t *testing.T) { }, }, configEntry: func() api.ConfigEntry { - ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "pd") + ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "global") pd := ce.(*api.ProxyConfigEntry) pd.MeshGateway.Mode = api.MeshGatewayModeLocal return pd @@ -516,7 +516,7 @@ func TestProcessUpstreams(t *testing.T) { }, }, configEntry: func() api.ConfigEntry { - ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "pd") + ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "global") pd := ce.(*api.ProxyConfigEntry) pd.MeshGateway.Mode = api.MeshGatewayModeRemote return pd @@ -533,7 +533,7 @@ func TestProcessUpstreams(t *testing.T) { }, expErr: "", configEntry: func() api.ConfigEntry { - ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "pd") + ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "global") pd := ce.(*api.ProxyConfigEntry) pd.MeshGateway.Mode = "remote" return pd @@ -634,7 +634,7 @@ func TestProcessUpstreams(t *testing.T) { return pod1 }, configEntry: func() api.ConfigEntry { - ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "pd") + ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "global") pd := ce.(*api.ProxyConfigEntry) pd.MeshGateway.Mode = "remote" return pd @@ -670,7 +670,7 @@ func TestProcessUpstreams(t *testing.T) { return pod1 }, configEntry: func() api.ConfigEntry { - ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "pd") + ce, _ := api.MakeConfigEntry(api.ProxyDefaults, "global") pd := ce.(*api.ProxyConfigEntry) pd.MeshGateway.Mode = "remote" return pd diff --git a/control-plane/connect-inject/peering_dialer_controller_test.go b/control-plane/connect-inject/peering_dialer_controller_test.go index 70076c75ec..62cb618d90 100644 --- a/control-plane/connect-inject/peering_dialer_controller_test.go +++ b/control-plane/connect-inject/peering_dialer_controller_test.go @@ -255,6 +255,7 @@ func TestReconcile_CreateUpdatePeeringDialer(t *testing.T) { // must be unique on the acceptor and dialer peers. Otherwise the following consul error will be thrown: // https://github.com/hashicorp/consul/blob/74b87d49d33069a048aead7a86d85d4b4b6461b5/agent/rpc/peering/service.go#L491. c.Datacenter = "acceptor-dc" + c.Ports.HTTPS = 0 }) require.NoError(t, err) defer acceptorPeerServer.Stop() @@ -438,6 +439,7 @@ func TestReconcile_VersionAnnotationPeeringDialer(t *testing.T) { // We set the datacenter because the server name, typically formatted as "server.." // must be unique on the acceptor and dialer peers. c.Datacenter = "acceptor-dc" + c.Ports.HTTPS = 0 }) require.NoError(t, err) defer acceptorPeerServer.Stop() diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 082ffeb1f3..4f0607732d 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,7 +14,7 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.0" + Version = "0.49.1" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release From eb369d53538efb6a2a33c90c79c548a89eb9a28d Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Tue, 15 Nov 2022 21:32:10 +0000 Subject: [PATCH 182/235] backport of commit 9cb4489d01abb3ddc865edb3d70b33bdb95702bc --- .release/ci.hcl | 1 + 1 file changed, 1 insertion(+) diff --git a/.release/ci.hcl b/.release/ci.hcl index cf905516f1..ffc2fd60d5 100644 --- a/.release/ci.hcl +++ b/.release/ci.hcl @@ -191,6 +191,7 @@ event "promote-staging" { organization = "hashicorp" repository = "crt-workflows-common" workflow = "promote-staging" + config = "release-metadata.hcl" } notification { From cccc1a89bbd92c88b43d4da8c9d1b60be612e841 Mon Sep 17 00:00:00 2001 From: Nitya Dhanushkodi Date: Wed, 16 Nov 2022 09:12:05 -0800 Subject: [PATCH 183/235] set release back into dev mode (#1724) --- CHANGELOG.md | 2 ++ charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33a8d51fd5..972080f00e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.49.1 (November 14, 2022) BREAKING CHANGES: * Peering: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index a85b87ccfd..caf7e23a08 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.1 +version: 0.49.2-dev appVersion: 1.13.3 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: false + artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.3 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.1 + image: hashicorp/consul-k8s-control-plane:0.49.2-dev - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 7bf0c772c7..367b816089 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.1 + imageK8S: hashicorp/consul-k8s-control-plane:0.49.2-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 4f0607732d..42c4088e43 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.1" + Version = "0.49.2" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 4f0607732d..42c4088e43 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.1" + Version = "0.49.2" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 619870802d126ef45db1f565594e4a01372a9eef Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Wed, 16 Nov 2022 12:56:05 -0800 Subject: [PATCH 184/235] Backport of Dockerfile: bump up ubi-minimal image to 9.1 into release/0.49.x (#1728) * backport of commit a6f01f36a8ac775539f47bf5036d420e50228814 Co-authored-by: David Yu --- CHANGELOG.md | 4 ++++ control-plane/Dockerfile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 972080f00e..c143631db7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +IMPROVEMENTS: +* Control Plane + * Bump Dockerfile base image for RedHat UBI `consul-k8s-control-plane` image to `ubi-minimal:9.1`. [[GH-1725](https://github.com/hashicorp/consul-k8s/pull/1725)] + ## 0.49.1 (November 14, 2022) BREAKING CHANGES: * Peering: diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 802ec4fab2..921ac69784 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -111,7 +111,7 @@ CMD /bin/${BIN_NAME} # We don't rebuild the software because we want the exact checksums and # binary signatures to match the software and our builds aren't fully # reproducible currently. -FROM registry.access.redhat.com/ubi8/ubi-minimal:8.6 as ubi +FROM registry.access.redhat.com/ubi9-minimal:9.1.0 as ubi ARG PRODUCT_NAME ARG PRODUCT_VERSION From d70a468392ed89d6190613f4a97f9cda79f565fc Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Fri, 18 Nov 2022 16:03:04 -0800 Subject: [PATCH 185/235] Add support for LocalConnectTimeoutMs and LocalRequestTimeoutMs on service-defaults CRD (#1647) (#1748) * Add support for LocalConnectTimeoutMs and LocalRequestTimeoutMs on the Service Defaults CRD * auto gen code * revert the change from make ctrl-generate ctrl-manifests Co-authored-by: Zhouyang Zhang <84437068+erdanzhang@users.noreply.github.com> --- .../consul/templates/crd-servicedefaults.yaml | 11 +++++++++++ .../api/v1alpha1/servicedefaults_types.go | 17 +++++++++++++++++ .../api/v1alpha1/servicedefaults_types_test.go | 4 ++++ .../api/v1alpha1/zz_generated.deepcopy.go | 7 ++++++- .../consul.hashicorp.com_servicedefaults.yaml | 11 +++++++++++ .../controller/configentry_controller_test.go | 4 ++++ 6 files changed, 53 insertions(+), 1 deletion(-) diff --git a/charts/consul/templates/crd-servicedefaults.yaml b/charts/consul/templates/crd-servicedefaults.yaml index 636e8ce51f..1cf42673a8 100644 --- a/charts/consul/templates/crd-servicedefaults.yaml +++ b/charts/consul/templates/crd-servicedefaults.yaml @@ -113,6 +113,17 @@ spec: TLS SNI value to be changed to a non-connect value when federating with an external system. type: string + localConnectTimeoutMs: + description: The number of milliseconds allowed to make connections + to the local application instance before timing out. Defaults to + 5000. + type: integer + localRequestTimeoutMs: + description: In milliseconds, the timeout for HTTP requests to the + local application instance. Applies to HTTP-based protocols only. + If not specified, inherits the Envoy default for route timeouts + (15s). + type: integer maxInboundConnections: description: MaxInboundConnections is the maximum number of concurrent inbound connections to each service instance. Defaults to 0 (using diff --git a/control-plane/api/v1alpha1/servicedefaults_types.go b/control-plane/api/v1alpha1/servicedefaults_types.go index b3902c4118..41a536e855 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types.go +++ b/control-plane/api/v1alpha1/servicedefaults_types.go @@ -87,6 +87,13 @@ type ServiceDefaultsSpec struct { // MaxInboundConnections is the maximum number of concurrent inbound connections to // each service instance. Defaults to 0 (using consul's default) if not set. MaxInboundConnections int `json:"maxInboundConnections,omitempty"` + // The number of milliseconds allowed to make connections to the local application + // instance before timing out. Defaults to 5000. + LocalConnectTimeoutMs int `json:"localConnectTimeoutMs,omitempty"` + // In milliseconds, the timeout for HTTP requests to the local application instance. + // Applies to HTTP-based protocols only. If not specified, inherits the Envoy default for + // route timeouts (15s). + LocalRequestTimeoutMs int `json:"localRequestTimeoutMs,omitempty"` } type Upstreams struct { @@ -263,6 +270,8 @@ func (in *ServiceDefaults) ToConsul(datacenter string) capi.ConfigEntry { Destination: in.Spec.Destination.toConsul(), Meta: meta(datacenter), MaxInboundConnections: in.Spec.MaxInboundConnections, + LocalConnectTimeoutMs: in.Spec.LocalConnectTimeoutMs, + LocalRequestTimeoutMs: in.Spec.LocalRequestTimeoutMs, } } @@ -293,6 +302,14 @@ func (in *ServiceDefaults) Validate(consulMeta common.ConsulMeta) error { allErrs = append(allErrs, field.Invalid(path.Child("maxinboundconnections"), in.Spec.MaxInboundConnections, "MaxInboundConnections must be > 0")) } + if in.Spec.LocalConnectTimeoutMs < 0 { + allErrs = append(allErrs, field.Invalid(path.Child("localConnectTimeoutMs"), in.Spec.LocalConnectTimeoutMs, "LocalConnectTimeoutMs must be > 0")) + } + + if in.Spec.LocalRequestTimeoutMs < 0 { + allErrs = append(allErrs, field.Invalid(path.Child("localRequestTimeoutMs"), in.Spec.LocalRequestTimeoutMs, "LocalRequestTimeoutMs must be > 0")) + } + allErrs = append(allErrs, in.Spec.UpstreamConfig.validate(path.Child("upstreamConfig"), consulMeta.PartitionsEnabled)...) allErrs = append(allErrs, in.Spec.Expose.validate(path.Child("expose"))...) diff --git a/control-plane/api/v1alpha1/servicedefaults_types_test.go b/control-plane/api/v1alpha1/servicedefaults_types_test.go index c70c8a6408..e7fdae2575 100644 --- a/control-plane/api/v1alpha1/servicedefaults_types_test.go +++ b/control-plane/api/v1alpha1/servicedefaults_types_test.go @@ -146,6 +146,8 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Port: 443, }, MaxInboundConnections: 20, + LocalConnectTimeoutMs: 5000, + LocalRequestTimeoutMs: 15000, }, }, &capi.ServiceConfigEntry{ @@ -252,6 +254,8 @@ func TestServiceDefaults_ToConsul(t *testing.T) { Port: 443, }, MaxInboundConnections: 20, + LocalConnectTimeoutMs: 5000, + LocalRequestTimeoutMs: 15000, Meta: map[string]string{ common.SourceKey: common.SourceValue, common.DatacenterKey: "datacenter", diff --git a/control-plane/api/v1alpha1/zz_generated.deepcopy.go b/control-plane/api/v1alpha1/zz_generated.deepcopy.go index cacef8c64c..0ad0cbf254 100644 --- a/control-plane/api/v1alpha1/zz_generated.deepcopy.go +++ b/control-plane/api/v1alpha1/zz_generated.deepcopy.go @@ -838,6 +838,11 @@ func (in *MeshTLSConfig) DeepCopy() *MeshTLSConfig { func (in *PassiveHealthCheck) DeepCopyInto(out *PassiveHealthCheck) { *out = *in out.Interval = in.Interval + if in.EnforcingConsecutive5xx != nil { + in, out := &in.EnforcingConsecutive5xx, &out.EnforcingConsecutive5xx + *out = new(uint32) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PassiveHealthCheck. @@ -2186,7 +2191,7 @@ func (in *Upstream) DeepCopyInto(out *Upstream) { if in.PassiveHealthCheck != nil { in, out := &in.PassiveHealthCheck, &out.PassiveHealthCheck *out = new(PassiveHealthCheck) - **out = **in + (*in).DeepCopyInto(*out) } out.MeshGateway = in.MeshGateway } diff --git a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml index ae815fce47..944f494f98 100644 --- a/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml +++ b/control-plane/config/crd/bases/consul.hashicorp.com_servicedefaults.yaml @@ -106,6 +106,17 @@ spec: TLS SNI value to be changed to a non-connect value when federating with an external system. type: string + localConnectTimeoutMs: + description: The number of milliseconds allowed to make connections + to the local application instance before timing out. Defaults to + 5000. + type: integer + localRequestTimeoutMs: + description: In milliseconds, the timeout for HTTP requests to the + local application instance. Applies to HTTP-based protocols only. + If not specified, inherits the Envoy default for route timeouts + (15s). + type: integer maxInboundConnections: description: MaxInboundConnections is the maximum number of concurrent inbound connections to each service instance. Defaults to 0 (using diff --git a/control-plane/controller/configentry_controller_test.go b/control-plane/controller/configentry_controller_test.go index 5a26d9abd6..1df9364d5f 100644 --- a/control-plane/controller/configentry_controller_test.go +++ b/control-plane/controller/configentry_controller_test.go @@ -53,6 +53,8 @@ func TestConfigEntryControllers_createsConfigEntry(t *testing.T) { Spec: v1alpha1.ServiceDefaultsSpec{ Protocol: "http", MaxInboundConnections: 100, + LocalConnectTimeoutMs: 5000, + LocalRequestTimeoutMs: 15000, }, }, reconciler: func(client client.Client, consulClient *capi.Client, logger logr.Logger) testReconciler { @@ -70,6 +72,8 @@ func TestConfigEntryControllers_createsConfigEntry(t *testing.T) { require.True(t, ok, "cast error") require.Equal(t, "http", svcDefault.Protocol) require.Equal(t, 100, svcDefault.MaxInboundConnections) + require.Equal(t, 5000, svcDefault.LocalConnectTimeoutMs) + require.Equal(t, 15000, svcDefault.LocalRequestTimeoutMs) }, }, { From 931d7ab7fa03880c8cc5715030856dc8c819271d Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Mon, 21 Nov 2022 09:26:57 -0800 Subject: [PATCH 186/235] Backport of Disable PodSecurityPolicy when global.enablePodSecurityPolicies set to false into release/0.49.x (#1745) * no-op commit due to failed cherry-picking * Disable PodSecurityPolicy when global.enablePodSecurityPolicies set to false (#1693) Co-authored-by: temp Co-authored-by: James (Anh-Tu) Nguyen --- ...yption-autogenerate-podsecuritypolicy.yaml | 2 +- .../partition-init-podsecuritypolicy.yaml | 2 +- ...yption-autogenerate-podsecuritypolicy.bats | 21 ++++++- .../partition-init-podsecuritypolicy.bats | 60 +++++++++++++++++-- 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/charts/consul/templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml b/charts/consul/templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml index 707ebe57c9..209b3aa343 100644 --- a/charts/consul/templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml +++ b/charts/consul/templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml @@ -1,4 +1,4 @@ -{{- if .Values.global.gossipEncryption.autoGenerate }} +{{- if and .Values.global.gossipEncryption.autoGenerate .Values.global.enablePodSecurityPolicies }} --- apiVersion: policy/v1beta1 kind: PodSecurityPolicy diff --git a/charts/consul/templates/partition-init-podsecuritypolicy.yaml b/charts/consul/templates/partition-init-podsecuritypolicy.yaml index 8590a691dd..2bc6782394 100644 --- a/charts/consul/templates/partition-init-podsecuritypolicy.yaml +++ b/charts/consul/templates/partition-init-podsecuritypolicy.yaml @@ -1,5 +1,5 @@ {{- $serverEnabled := (or (and (ne (.Values.server.enabled | toString) "-") .Values.server.enabled) (and (eq (.Values.server.enabled | toString) "-") .Values.global.enabled)) -}} -{{- if (and .Values.global.adminPartitions.enabled (not $serverEnabled)) }} +{{- if (and .Values.global.adminPartitions.enabled .Values.global.enablePodSecurityPolicies (not $serverEnabled)) }} apiVersion: policy/v1beta1 kind: PodSecurityPolicy metadata: diff --git a/charts/consul/test/unit/gossip-encryption-autogenerate-podsecuritypolicy.bats b/charts/consul/test/unit/gossip-encryption-autogenerate-podsecuritypolicy.bats index 810147bed3..3ee4f4058a 100644 --- a/charts/consul/test/unit/gossip-encryption-autogenerate-podsecuritypolicy.bats +++ b/charts/consul/test/unit/gossip-encryption-autogenerate-podsecuritypolicy.bats @@ -17,11 +17,30 @@ load _helpers . } -@test "gossipEncryptionAutogenerate/PodSecurityPolicy: enabled with global.gossipEncryption.autoGenerate=true" { +@test "gossipEncryptionAutogenerate/PodSecurityPolicy: disabled with global.gossipEncryption.autoGenerate=true and global.enablePodSecurityPolicies=false" { + cd `chart_dir` + assert_empty helm template \ + -s templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml \ + --set 'global.gossipEncryption.autoGenerate=true' \ + --set 'global.enablePodSecurityPolicies=false' \ + . +} + +@test "gossipEncryptionAutogenerate/PodSecurityPolicy: disabled with global.gossipEncryption.autoGenerate=false and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml \ + --set 'global.gossipEncryption.autoGenerate=false' \ + --set 'global.enablePodSecurityPolicies=true' \ + . +} + +@test "gossipEncryptionAutogenerate/PodSecurityPolicy: enabled with global.gossipEncryption.autoGenerate=true and global.enablePodSecurityPolicies=true" { cd `chart_dir` local actual=$(helm template \ -s templates/gossip-encryption-autogenerate-podsecuritypolicy.yaml \ --set 'global.gossipEncryption.autoGenerate=true' \ + --set 'global.enablePodSecurityPolicies=true' \ . | tee /dev/stderr | yq -s 'length > 0' | tee /dev/stderr) [ "${actual}" = "true" ] diff --git a/charts/consul/test/unit/partition-init-podsecuritypolicy.bats b/charts/consul/test/unit/partition-init-podsecuritypolicy.bats index d00c915f6e..c7d4ce4ddd 100644 --- a/charts/consul/test/unit/partition-init-podsecuritypolicy.bats +++ b/charts/consul/test/unit/partition-init-podsecuritypolicy.bats @@ -9,40 +9,92 @@ load _helpers . } -@test "partitionInit/PodSecurityPolicy: enabled with global.adminPartitions.enabled=true and servers = false" { +@test "partitionInit/PodSecurityPolicy: enabled with global.adminPartitions.enabled=true and global.enablePodSecurityPolicies=true and server.enabled=false" { cd `chart_dir` local actual=$(helm template \ -s templates/partition-init-podsecuritypolicy.yaml \ --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=true' \ --set 'server.enabled=false' \ . | tee /dev/stderr | yq 'length > 0' | tee /dev/stderr) [ "${actual}" = "true" ] } -@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and servers = true" { +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and global.enablePodSecurityPolicies=false and server.enabled=false" { cd `chart_dir` assert_empty helm template \ -s templates/partition-init-podsecuritypolicy.yaml \ --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=false' \ + --set 'server.enabled=false' \ + . +} + +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and global.enablePodSecurityPolicies=true and servers = true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/partition-init-podsecuritypolicy.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=true' \ + --set 'server.enabled=true' \ + . +} + +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and global.enablePodSecurityPolicies=false and servers = true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/partition-init-podsecuritypolicy.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=false' \ --set 'server.enabled=true' \ . } -@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and global.enabled = true" { +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and global.enablePodSecurityPolicies=true and global.enabled = true" { cd `chart_dir` assert_empty helm template \ -s templates/partition-init-podsecuritypolicy.yaml \ --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=true' \ --set 'global.enabled=true' \ . } -@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=false" { +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=true and global.enablePodSecurityPolicies=false and global.enabled = true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/partition-init-podsecuritypolicy.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=false' \ + --set 'global.enabled=true' \ + . +} + +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=false and global.enablePodSecurityPolicies=true" { + cd `chart_dir` + assert_empty helm template \ + -s templates/partition-init-podsecuritypolicy.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=true' \ + --set 'server.enabled=true' \ + . +} + +@test "partitionInit/PodSecurityPolicy: disabled with global.adminPartitions.enabled=false and global.enablePodSecurityPolicies=false" { cd `chart_dir` assert_empty helm template \ -s templates/partition-init-podsecuritypolicy.yaml \ --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'global.enablePodSecurityPolicies=false' \ --set 'server.enabled=true' \ . } \ No newline at end of file From b2b16bf48efae0108d7cd8f074ebf3b62edc8fe0 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Thu, 1 Dec 2022 11:20:20 -0500 Subject: [PATCH 187/235] Release 0.49.2 (#1764) * Release 0.49.2 --- CHANGELOG.md | 8 +++++++- charts/consul/Chart.yaml | 10 +++++----- charts/consul/values.yaml | 4 ++-- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 5 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c143631db7..d9a0bc9f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,14 @@ -## UNRELEASED +## 0.49.2 (December 1, 2022) IMPROVEMENTS: * Control Plane * Bump Dockerfile base image for RedHat UBI `consul-k8s-control-plane` image to `ubi-minimal:9.1`. [[GH-1725](https://github.com/hashicorp/consul-k8s/pull/1725)] +* Helm + * Add fields `localConnectTimeoutMs` and `localRequestTimeoutMs` to the `ServiceDefaults` CRD. [[GH-1647](https://github.com/hashicorp/consul-k8s/pull/1647)] + +BUG FIXES: +* Helm: + * Disable PodSecurityPolicies templating for `gossip-encryption-autogenerate` and `partition-init` when `global.enablePodSecurityPolicies` is `false`. [[GH-1693](https://github.com/hashicorp/consul-k8s/pull/1693)] ## 0.49.1 (November 14, 2022) BREAKING CHANGES: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index caf7e23a08..fe8877e667 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul -version: 0.49.2-dev -appVersion: 1.13.3 +version: 0.49.2 +appVersion: 1.13.4 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: true + artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.13.3 + image: hashicorp/consul:1.13.4 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.2-dev + image: hashicorp/consul-k8s-control-plane:0.49.2 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 367b816089..9d0cb37a0f 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -109,7 +109,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.13.3" + image: "hashicorp/consul:1.13.4" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.2-dev + imageK8S: hashicorp/consul-k8s-control-plane:0.49.2 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 42c4088e43..cbb75dc281 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 42c4088e43..cbb75dc281 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From ab920e1485ad157fc6546369346b242c56c97650 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Mon, 5 Dec 2022 09:40:35 -0500 Subject: [PATCH 188/235] set to 0.49.3 dev mode (#1766) --- CHANGELOG.md | 2 ++ charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9a0bc9f61..3c6037715f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.49.2 (December 1, 2022) IMPROVEMENTS: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index fe8877e667..5df9536f37 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.2 +version: 0.49.3-dev appVersion: 1.13.4 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: false + artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.4 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.2 + image: hashicorp/consul-k8s-control-plane:0.49.3-dev - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 9d0cb37a0f..f36ebe6fb0 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.2 + imageK8S: hashicorp/consul-k8s-control-plane:0.49.3-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index cbb75dc281..c2a5437b2c 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.2" + Version = "0.49.3" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index cbb75dc281..c2a5437b2c 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.2" + Version = "0.49.3" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 6bdb8e63e2f97e85e3037c22852e6c94f20c9dcc Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 7 Dec 2022 16:13:05 -0500 Subject: [PATCH 189/235] Add global.extraLabels values.yaml setting (#1771) (#1778) * Add global.extraLabels values.yaml setting This setting lets you apply a set of labels to all pods created by the consul-k8s helm chart. * Also apply global extra labels to deployments/daemonsets/statefulsets/jobs * Add global extraLabels to sync catalog deployment Co-authored-by: Chris Bruce --- .../api-gateway-controller-deployment.yaml | 6 ++ charts/consul/templates/client-daemonset.yaml | 6 ++ charts/consul/templates/cni-daemonset.yaml | 6 ++ .../templates/connect-inject-deployment.yaml | 6 ++ .../create-federation-secret-job.yaml | 6 ++ .../templates/enterprise-license-job.yaml | 6 ++ .../gossip-encryption-autogenerate-job.yaml | 6 ++ .../ingress-gateways-deployment.yaml | 6 ++ .../templates/mesh-gateway-deployment.yaml | 8 ++- .../consul/templates/partition-init-job.yaml | 6 ++ .../server-acl-init-cleanup-job.yaml | 6 ++ .../consul/templates/server-acl-init-job.yaml | 6 ++ .../consul/templates/server-statefulset.yaml | 6 ++ .../templates/sync-catalog-deployment.yaml | 6 ++ .../terminating-gateways-deployment.yaml | 8 ++- .../templates/tls-init-cleanup-job.yaml | 6 ++ charts/consul/templates/tls-init-job.yaml | 6 ++ .../webhook-cert-manager-deployment.yaml | 6 ++ .../api-gateway-controller-deployment.bats | 47 +++++++++++++++ charts/consul/test/unit/client-daemonset.bats | 30 ++++++++++ charts/consul/test/unit/cni-daemonset.bats | 47 +++++++++++++++ .../test/unit/connect-inject-deployment.bats | 37 +++++++++++- .../unit/create-federation-secret-job.bats | 56 ++++++++++++++++++ .../test/unit/enterprise-license-job.bats | 50 ++++++++++++++++ .../gossip-encryption-autogenerate-job.bats | 44 ++++++++++++++ .../unit/ingress-gateways-deployment.bats | 49 ++++++++++++++- .../test/unit/mesh-gateway-deployment.bats | 47 +++++++++++++++ .../consul/test/unit/partition-init-job.bats | 59 +++++++++++++++++++ .../unit/server-acl-init-cleanup-job.bats | 44 ++++++++++++++ .../consul/test/unit/server-acl-init-job.bats | 44 ++++++++++++++ .../consul/test/unit/server-statefulset.bats | 29 +++++++++ .../test/unit/sync-catalog-deployment.bats | 32 ++++++++++ .../unit/terminating-gateways-deployment.bats | 47 +++++++++++++++ .../test/unit/tls-init-cleanup-job.bats | 44 ++++++++++++++ charts/consul/test/unit/tls-init-job.bats | 44 ++++++++++++++ .../unit/webhook-cert-manager-deployment.bats | 47 +++++++++++++++ charts/consul/values.yaml | 13 ++++ 37 files changed, 918 insertions(+), 4 deletions(-) diff --git a/charts/consul/templates/api-gateway-controller-deployment.yaml b/charts/consul/templates/api-gateway-controller-deployment.yaml index 604a017ecf..3018c0294b 100644 --- a/charts/consul/templates/api-gateway-controller-deployment.yaml +++ b/charts/consul/templates/api-gateway-controller-deployment.yaml @@ -13,6 +13,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: api-gateway-controller + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.apiGateway.controller.replicas }} selector: @@ -44,6 +47,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: api-gateway-controller + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} spec: serviceAccountName: {{ template "consul.fullname" . }}-api-gateway-controller containers: diff --git a/charts/consul/templates/client-daemonset.yaml b/charts/consul/templates/client-daemonset.yaml index 36edc70ddb..95a990b4fb 100644 --- a/charts/consul/templates/client-daemonset.yaml +++ b/charts/consul/templates/client-daemonset.yaml @@ -22,6 +22,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: client + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .Values.client.updateStrategy }} updateStrategy: @@ -45,6 +48,9 @@ spec: {{- if .Values.client.extraLabels }} {{- toYaml .Values.client.extraLabels | nindent 8 }} {{- end }} + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: {{- if .Values.global.secretsBackend.vault.enabled }} "vault.hashicorp.com/agent-inject": "true" diff --git a/charts/consul/templates/cni-daemonset.yaml b/charts/consul/templates/cni-daemonset.yaml index 7b9f90d939..1fe2e6a08d 100644 --- a/charts/consul/templates/cni-daemonset.yaml +++ b/charts/consul/templates/cni-daemonset.yaml @@ -11,6 +11,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: cni + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: {{- if .Values.connectInject.cni.updateStrategy }} updateStrategy: @@ -29,6 +32,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: cni + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: consul.hashicorp.com/connect-inject: "false" spec: diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 779dceb572..63fb5ae84c 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -26,6 +26,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: connect-injector + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.connectInject.replicas }} selector: @@ -41,6 +44,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: connect-injector + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" {{- if .Values.connectInject.annotations }} diff --git a/charts/consul/templates/create-federation-secret-job.yaml b/charts/consul/templates/create-federation-secret-job.yaml index 6bc2b9f4d8..daf97bb121 100644 --- a/charts/consul/templates/create-federation-secret-job.yaml +++ b/charts/consul/templates/create-federation-secret-job.yaml @@ -13,6 +13,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: create-federation-secret + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": post-install,post-upgrade {{- /* Hook weight needs to be 1 so that the service account is provisioned first */}} @@ -27,6 +30,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: create-federation-secret + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" spec: diff --git a/charts/consul/templates/enterprise-license-job.yaml b/charts/consul/templates/enterprise-license-job.yaml index 02921db3b0..0122690104 100644 --- a/charts/consul/templates/enterprise-license-job.yaml +++ b/charts/consul/templates/enterprise-license-job.yaml @@ -15,6 +15,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: license + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": post-install,post-upgrade "helm.sh/hook-weight": "100" @@ -31,6 +34,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: license + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" spec: diff --git a/charts/consul/templates/gossip-encryption-autogenerate-job.yaml b/charts/consul/templates/gossip-encryption-autogenerate-job.yaml index e1a6e49823..9d296478a1 100644 --- a/charts/consul/templates/gossip-encryption-autogenerate-job.yaml +++ b/charts/consul/templates/gossip-encryption-autogenerate-job.yaml @@ -14,6 +14,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: gossip-encryption-autogenerate + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": pre-install,pre-upgrade "helm.sh/hook-weight": "1" @@ -27,6 +30,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: gossip-encryption-autogenerate + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" spec: diff --git a/charts/consul/templates/ingress-gateways-deployment.yaml b/charts/consul/templates/ingress-gateways-deployment.yaml index 77a4d9dcd8..ed5724389e 100644 --- a/charts/consul/templates/ingress-gateways-deployment.yaml +++ b/charts/consul/templates/ingress-gateways-deployment.yaml @@ -46,6 +46,9 @@ metadata: release: {{ $root.Release.Name }} component: ingress-gateway ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }} + {{- if $root.Values.global.extraLabels }} + {{- toYaml $root.Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: {{ default $defaults.replicas .replicas }} selector: @@ -65,6 +68,9 @@ spec: release: {{ $root.Release.Name }} component: ingress-gateway ingress-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }} + {{- if $root.Values.global.extraLabels }} + {{- toYaml $root.Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: {{- if (and $root.Values.global.secretsBackend.vault.enabled $root.Values.global.tls.enabled) }} "vault.hashicorp.com/agent-init-first": "true" diff --git a/charts/consul/templates/mesh-gateway-deployment.yaml b/charts/consul/templates/mesh-gateway-deployment.yaml index ffe0036ded..a74abce318 100644 --- a/charts/consul/templates/mesh-gateway-deployment.yaml +++ b/charts/consul/templates/mesh-gateway-deployment.yaml @@ -19,6 +19,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: mesh-gateway + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: {{ .Values.meshGateway.replicas }} selector: @@ -34,6 +37,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: mesh-gateway + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" {{- if (and .Values.global.secretsBackend.vault.enabled .Values.global.tls.enabled) }} @@ -352,7 +358,7 @@ spec: lifecycle: preStop: exec: - command: + command: - "/bin/sh" - "-ec" - "/consul-bin/consul services deregister -id=\"{{ .Values.meshGateway.consulServiceName }}\"" diff --git a/charts/consul/templates/partition-init-job.yaml b/charts/consul/templates/partition-init-job.yaml index 4d6d971743..1b17e721be 100644 --- a/charts/consul/templates/partition-init-job.yaml +++ b/charts/consul/templates/partition-init-job.yaml @@ -14,6 +14,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: partition-init + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": pre-install "helm.sh/hook-weight": "2" @@ -27,6 +30,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: partition-init + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" {{- if (and .Values.global.secretsBackend.vault.enabled (or .Values.global.tls.enabled .Values.global.acls.manageSystemACLs)) }} diff --git a/charts/consul/templates/server-acl-init-cleanup-job.yaml b/charts/consul/templates/server-acl-init-cleanup-job.yaml index 697427ab5f..35b0877ab4 100644 --- a/charts/consul/templates/server-acl-init-cleanup-job.yaml +++ b/charts/consul/templates/server-acl-init-cleanup-job.yaml @@ -23,6 +23,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: server-acl-init-cleanup + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": post-install,post-upgrade "helm.sh/hook-weight": "0" @@ -39,6 +42,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: server-acl-init-cleanup + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" spec: diff --git a/charts/consul/templates/server-acl-init-job.yaml b/charts/consul/templates/server-acl-init-job.yaml index b2f770db7a..21fd018656 100644 --- a/charts/consul/templates/server-acl-init-job.yaml +++ b/charts/consul/templates/server-acl-init-job.yaml @@ -27,6 +27,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: server-acl-init + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: template: metadata: @@ -36,6 +39,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: server-acl-init + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" {{- if .Values.global.secretsBackend.vault.enabled }} diff --git a/charts/consul/templates/server-statefulset.yaml b/charts/consul/templates/server-statefulset.yaml index 71b424cc68..fa775cd0bc 100644 --- a/charts/consul/templates/server-statefulset.yaml +++ b/charts/consul/templates/server-statefulset.yaml @@ -28,6 +28,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: server + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: serviceName: {{ template "consul.fullname" . }}-server podManagementPolicy: Parallel @@ -56,6 +59,9 @@ spec: {{- if .Values.server.extraLabels }} {{- toYaml .Values.server.extraLabels | nindent 8 }} {{- end }} + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: {{- if .Values.global.secretsBackend.vault.enabled }} "vault.hashicorp.com/agent-inject": "true" diff --git a/charts/consul/templates/sync-catalog-deployment.yaml b/charts/consul/templates/sync-catalog-deployment.yaml index 4c8b4359da..d64ca05f62 100644 --- a/charts/consul/templates/sync-catalog-deployment.yaml +++ b/charts/consul/templates/sync-catalog-deployment.yaml @@ -13,6 +13,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: sync-catalog + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: 1 selector: @@ -31,6 +34,9 @@ spec: {{- if .Values.syncCatalog.extraLabels }} {{- toYaml .Values.syncCatalog.extraLabels | nindent 8 }} {{- end }} + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" {{- if .Values.syncCatalog.annotations }} diff --git a/charts/consul/templates/terminating-gateways-deployment.yaml b/charts/consul/templates/terminating-gateways-deployment.yaml index acdab29af8..540fded2e6 100644 --- a/charts/consul/templates/terminating-gateways-deployment.yaml +++ b/charts/consul/templates/terminating-gateways-deployment.yaml @@ -49,6 +49,9 @@ metadata: release: {{ $root.Release.Name }} component: terminating-gateway terminating-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }} + {{- if $root.Values.global.extraLabels }} + {{- toYaml $root.Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: {{ default $defaults.replicas .replicas }} selector: @@ -68,6 +71,9 @@ spec: release: {{ $root.Release.Name }} component: terminating-gateway terminating-gateway-name: {{ template "consul.fullname" $root }}-{{ .name }} + {{- if $root.Values.global.extraLabels }} + {{- toYaml $root.Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: {{- if (and $root.Values.global.secretsBackend.vault.enabled $root.Values.global.tls.enabled) }} "vault.hashicorp.com/agent-init-first": "true" @@ -199,7 +205,7 @@ spec: - name: CONSUL_HTTP_ADDR value: http://$(HOST_IP):8500 {{- end }} - command: + command: - "/bin/sh" - "-ec" - | diff --git a/charts/consul/templates/tls-init-cleanup-job.yaml b/charts/consul/templates/tls-init-cleanup-job.yaml index 9a8898cc10..ba29bb84ae 100644 --- a/charts/consul/templates/tls-init-cleanup-job.yaml +++ b/charts/consul/templates/tls-init-cleanup-job.yaml @@ -13,6 +13,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: tls-init-cleanup + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": pre-delete "helm.sh/hook-delete-policy": hook-succeeded @@ -27,6 +30,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: tls-init-cleanup + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" spec: diff --git a/charts/consul/templates/tls-init-job.yaml b/charts/consul/templates/tls-init-job.yaml index 47dd6462b0..d002ae7a75 100644 --- a/charts/consul/templates/tls-init-job.yaml +++ b/charts/consul/templates/tls-init-job.yaml @@ -14,6 +14,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: tls-init + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} annotations: "helm.sh/hook": pre-install,pre-upgrade "helm.sh/hook-weight": "1" @@ -27,6 +30,9 @@ spec: chart: {{ template "consul.chart" . }} release: {{ .Release.Name }} component: tls-init + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" spec: diff --git a/charts/consul/templates/webhook-cert-manager-deployment.yaml b/charts/consul/templates/webhook-cert-manager-deployment.yaml index eef13e78b6..838f31b923 100644 --- a/charts/consul/templates/webhook-cert-manager-deployment.yaml +++ b/charts/consul/templates/webhook-cert-manager-deployment.yaml @@ -11,6 +11,9 @@ metadata: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: webhook-cert-manager + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 4 }} + {{- end }} spec: replicas: 1 selector: @@ -28,6 +31,9 @@ spec: heritage: {{ .Release.Service }} release: {{ .Release.Name }} component: webhook-cert-manager + {{- if .Values.global.extraLabels }} + {{- toYaml .Values.global.extraLabels | nindent 8 }} + {{- end }} annotations: "consul.hashicorp.com/connect-inject": "false" "consul.hashicorp.com/config-checksum": {{ include (print $.Template.BasePath "/webhook-cert-manager-configmap.yaml") . | sha256sum }} diff --git a/charts/consul/test/unit/api-gateway-controller-deployment.bats b/charts/consul/test/unit/api-gateway-controller-deployment.bats index 60adc84076..543cdaecd7 100755 --- a/charts/consul/test/unit/api-gateway-controller-deployment.bats +++ b/charts/consul/test/unit/api-gateway-controller-deployment.bats @@ -904,3 +904,50 @@ load _helpers yq -r '.spec.template.metadata.annotations.foo' | tee /dev/stderr) [ "${actual}" = "bar" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "apiGateway/Deployment: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-deployment.yaml \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=bar' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "apiGateway/Deployment: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-deployment.yaml \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=bar' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "apiGateway/Deployment: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/api-gateway-controller-deployment.yaml \ + --set 'apiGateway.enabled=true' \ + --set 'apiGateway.image=bar' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/client-daemonset.bats b/charts/consul/test/unit/client-daemonset.bats index 24cc4324f2..c7e533cc08 100755 --- a/charts/consul/test/unit/client-daemonset.bats +++ b/charts/consul/test/unit/client-daemonset.bats @@ -465,6 +465,36 @@ load _helpers [ "${actualBaz}" = "qux" ] } +@test "client/DaemonSet: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/client-daemonset.yaml \ + --set 'client.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "client/DaemonSet: multiple extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/client-daemonset.yaml \ + --set 'client.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} #-------------------------------------------------------------------- # annotations diff --git a/charts/consul/test/unit/cni-daemonset.bats b/charts/consul/test/unit/cni-daemonset.bats index 0c423abfec..ccfce1b4b5 100644 --- a/charts/consul/test/unit/cni-daemonset.bats +++ b/charts/consul/test/unit/cni-daemonset.bats @@ -296,3 +296,50 @@ rollingUpdate: [ "${actual}" = '{"mountPath":"bar","name":"cni-net-dir"}' ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "cni/DaemonSet: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "cni/DaemonSet: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "cni/DaemonSet: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/cni-daemonset.yaml \ + --set 'connectInject.cni.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index 8ab6c3855f..b84efc0808 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1692,6 +1692,41 @@ EOF [ "${actual}" = "name" ] } +#-------------------------------------------------------------------- +# extraLabels + +@test "connectInject/Deployment: can set extra global labels" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "connectInject/Deployment: can set multiple extra global labels" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/connect-inject-deployment.yaml \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} + #-------------------------------------------------------------------- # annotations @@ -2348,7 +2383,7 @@ EOF local actual="$(echo $cmd | yq -r '.annotations["vault.hashicorp.com/secret-volume-path-ca.crt"]' | tee /dev/stderr)" [ "${actual}" = "/vault/secrets/connect-injector/certs" ] - + local actual="$(echo $cmd | yq -r '.annotations["vault.hashicorp.com/agent-init-first"]' | tee /dev/stderr)" [ "${actual}" = "true" ] diff --git a/charts/consul/test/unit/create-federation-secret-job.bats b/charts/consul/test/unit/create-federation-secret-job.bats index a3343db582..5a569d2670 100644 --- a/charts/consul/test/unit/create-federation-secret-job.bats +++ b/charts/consul/test/unit/create-federation-secret-job.bats @@ -422,3 +422,59 @@ load _helpers actual=$(echo $command | jq ' . | contains("-consul-api-timeout=5s")') [ "${actual}" = "true" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "createFederationSecret/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/create-federation-secret-job.yaml \ + --set 'global.federation.enabled=true' \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.federation.createFederationSecret=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "createFederationSecret/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/create-federation-secret-job.yaml \ + --set 'global.federation.enabled=true' \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.federation.createFederationSecret=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "createFederationSecret/Job: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/create-federation-secret-job.yaml \ + --set 'global.federation.enabled=true' \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.tls.enabled=true' \ + --set 'global.federation.createFederationSecret=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/enterprise-license-job.bats b/charts/consul/test/unit/enterprise-license-job.bats index 5652419bb3..dcc844eb30 100644 --- a/charts/consul/test/unit/enterprise-license-job.bats +++ b/charts/consul/test/unit/enterprise-license-job.bats @@ -212,3 +212,53 @@ load _helpers actual=$(echo $ca_cert_volume | jq -r '.secret.items[0].key' | tee /dev/stderr) [ "${actual}" = "key" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "enterpriseLicense/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/enterprise-license-job.yaml \ + --set 'global.enterpriseLicense.secretName=foo' \ + --set 'global.enterpriseLicense.secretKey=bar' \ + --set 'global.enterpriseLicense.enableLicenseAutoload=false' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component") | del(."app.kubernetes.io/managed-by") | del(."app.kubernetes.io/instance") | del(."helm.sh/chart")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "enterpriseLicense/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/enterprise-license-job.yaml \ + --set 'global.enterpriseLicense.secretName=foo' \ + --set 'global.enterpriseLicense.secretKey=bar' \ + --set 'global.enterpriseLicense.enableLicenseAutoload=false' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "enterpriseLicense/Job: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/enterprise-license-job.yaml \ + --set 'global.enterpriseLicense.secretName=foo' \ + --set 'global.enterpriseLicense.secretKey=bar' \ + --set 'global.enterpriseLicense.enableLicenseAutoload=false' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats b/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats index 87cc5a5990..662b523bc0 100644 --- a/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats +++ b/charts/consul/test/unit/gossip-encryption-autogenerate-job.bats @@ -61,3 +61,47 @@ load _helpers yq -r '.spec.template.spec | has("securityContext")' | tee /dev/stderr) [ "${has_security_context}" = "false" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "gossipEncryptionAutogenerate/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/gossip-encryption-autogenerate-job.yaml \ + --set 'global.gossipEncryption.autoGenerate=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "gossipEncryptionAutogenerate/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/gossip-encryption-autogenerate-job.yaml \ + --set 'global.gossipEncryption.autoGenerate=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "gossipEncryptionAutogenerate/Job: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/gossip-encryption-autogenerate-job.yaml \ + --set 'global.gossipEncryption.autoGenerate=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/ingress-gateways-deployment.bats b/charts/consul/test/unit/ingress-gateways-deployment.bats index 340aa4429b..f4bbc40881 100644 --- a/charts/consul/test/unit/ingress-gateways-deployment.bats +++ b/charts/consul/test/unit/ingress-gateways-deployment.bats @@ -945,7 +945,7 @@ load _helpers #-------------------------------------------------------------------- # topologySpreadConstraints -@test "ingressGateways/Deployment: topologySpreadConstraints not set by default" { +@test "ingressGateways/Deployment: topologySpreadConstraints not set by default" { cd `chart_dir` local actual=$(helm template \ -s templates/ingress-gateways-deployment.yaml \ @@ -1925,3 +1925,50 @@ EOF yq -s -r '.[0].spec.template.spec.terminationGracePeriodSeconds' | tee /dev/stderr) [ "${actual}" = "30" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "ingressGateways/Deployment: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/ingress-gateways-deployment.yaml \ + --set 'ingressGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component") | del(."heritage") | del(."ingress-gateway-name") | del(."consul.hashicorp.com/connect-inject-managed-by")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "ingressGateways/Deployment: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/ingress-gateways-deployment.yaml \ + --set 'ingressGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "ingressGateways/Deployment: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/ingress-gateways-deployment.yaml \ + --set 'ingressGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/mesh-gateway-deployment.bats b/charts/consul/test/unit/mesh-gateway-deployment.bats index 2cf47ee748..300886e713 100755 --- a/charts/consul/test/unit/mesh-gateway-deployment.bats +++ b/charts/consul/test/unit/mesh-gateway-deployment.bats @@ -1990,3 +1990,50 @@ EOF yq -r '.spec.template.metadata.annotations.foo' | tee /dev/stderr) [ "${actual}" = "bar" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "meshGateway/Deployment: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/mesh-gateway-deployment.yaml \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component") | del(."consul.hashicorp.com/connect-inject-managed-by")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "meshGateway/Deployment: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/mesh-gateway-deployment.yaml \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "meshGateway/Deployment: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/mesh-gateway-deployment.yaml \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/partition-init-job.bats b/charts/consul/test/unit/partition-init-job.bats index 816ad26ede..75c6df70ca 100644 --- a/charts/consul/test/unit/partition-init-job.bats +++ b/charts/consul/test/unit/partition-init-job.bats @@ -538,3 +538,62 @@ reservedNameTest() { yq -r '.spec.template.metadata.annotations.foo' | tee /dev/stderr) [ "${actual}" = "bar" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "partitionInit/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/partition-init-job.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'server.enabled=false' \ + --set 'global.adminPartitions.name=bar' \ + --set 'externalServers.enabled=true' \ + --set 'externalServers.hosts[0]=foo' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "partitionInit/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/partition-init-job.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'server.enabled=false' \ + --set 'global.adminPartitions.name=bar' \ + --set 'externalServers.enabled=true' \ + --set 'externalServers.hosts[0]=foo' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "partitionInit/Job: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/partition-init-job.yaml \ + --set 'global.adminPartitions.enabled=true' \ + --set 'global.enableConsulNamespaces=true' \ + --set 'server.enabled=false' \ + --set 'global.adminPartitions.name=bar' \ + --set 'externalServers.enabled=true' \ + --set 'externalServers.hosts[0]=foo' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/server-acl-init-cleanup-job.bats b/charts/consul/test/unit/server-acl-init-cleanup-job.bats index cb57374116..947cfa9b42 100644 --- a/charts/consul/test/unit/server-acl-init-cleanup-job.bats +++ b/charts/consul/test/unit/server-acl-init-cleanup-job.bats @@ -115,3 +115,47 @@ load _helpers yq -r '.spec.template.spec.nodeSelector[0].key' | tee /dev/stderr) [ "${actual}" = "value" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "serverACLInitCleanup/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-cleanup-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "serverACLInitCleanup/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-cleanup-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "serverACLInitCleanup/Job: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-cleanup-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/server-acl-init-job.bats b/charts/consul/test/unit/server-acl-init-job.bats index cc9bfb5f77..570d3a396e 100644 --- a/charts/consul/test/unit/server-acl-init-job.bats +++ b/charts/consul/test/unit/server-acl-init-job.bats @@ -1927,3 +1927,47 @@ load _helpers yq '.spec.template.spec.containers[0].command | any(contains("-federation"))' | tee /dev/stderr) [ "${actual}" = "true" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "serverACLInit/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "serverACLInit/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "serverACLInit/Job: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-acl-init-job.yaml \ + --set 'global.acls.manageSystemACLs=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/server-statefulset.bats b/charts/consul/test/unit/server-statefulset.bats index a725162e01..a6cccccb79 100755 --- a/charts/consul/test/unit/server-statefulset.bats +++ b/charts/consul/test/unit/server-statefulset.bats @@ -589,6 +589,35 @@ load _helpers [ "${actualBaz}" = "qux" ] } +@test "server/StatefulSet: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-statefulset.yaml \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "server/StatefulSet: multiple extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/server-statefulset.yaml \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} + #-------------------------------------------------------------------- # DNS diff --git a/charts/consul/test/unit/sync-catalog-deployment.bats b/charts/consul/test/unit/sync-catalog-deployment.bats index 0e0ac33a88..797432e21a 100755 --- a/charts/consul/test/unit/sync-catalog-deployment.bats +++ b/charts/consul/test/unit/sync-catalog-deployment.bats @@ -1217,6 +1217,38 @@ load _helpers [ "${actual}" = "bar" ] } +@test "syncCatalog/Deployment: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/sync-catalog-deployment.yaml \ + --set 'syncCatalog.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "syncCatalog/Deployment: multiple extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/sync-catalog-deployment.yaml \ + --set 'syncCatalog.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} + + #-------------------------------------------------------------------- # annotations diff --git a/charts/consul/test/unit/terminating-gateways-deployment.bats b/charts/consul/test/unit/terminating-gateways-deployment.bats index 61fa50bb84..5165c63565 100644 --- a/charts/consul/test/unit/terminating-gateways-deployment.bats +++ b/charts/consul/test/unit/terminating-gateways-deployment.bats @@ -1698,3 +1698,50 @@ EOF yq -r '.spec.template.metadata.annotations.foo' | tee /dev/stderr) [ "${actual}" = "bar" ] } + +#-------------------------------------------------------------------- +# extraLabels + +@test "terminatingGateways/Deployment: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/terminating-gateways-deployment.yaml \ + --set 'terminatingGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component") | del(."heritage") | del(."terminating-gateway-name") | del(."consul.hashicorp.com/connect-inject-managed-by")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "terminatingGateways/Deployment: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/terminating-gateways-deployment.yaml \ + --set 'terminatingGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "terminatingGateways/Deployment: multiple extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/terminating-gateways-deployment.yaml \ + --set 'terminatingGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/tls-init-cleanup-job.bats b/charts/consul/test/unit/tls-init-cleanup-job.bats index 76da65bfe5..04b4a2df31 100644 --- a/charts/consul/test/unit/tls-init-cleanup-job.bats +++ b/charts/consul/test/unit/tls-init-cleanup-job.bats @@ -75,3 +75,47 @@ load _helpers --set 'global.tls.enableAutoEncrypt=true' \ . } + +#-------------------------------------------------------------------- +# extraLabels + +@test "tlsInit/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/tls-init-cleanup-job.yaml \ + --set 'global.tls.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "tlsInit/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/tls-init-cleanup-job.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "tlsInit/Job: multiple extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/tls-init-cleanup-job.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/tls-init-job.bats b/charts/consul/test/unit/tls-init-job.bats index 6c148ed074..f9294915a5 100644 --- a/charts/consul/test/unit/tls-init-job.bats +++ b/charts/consul/test/unit/tls-init-job.bats @@ -163,3 +163,47 @@ load _helpers --set 'global.tls.enableAutoEncrypt=true' \ . } + +#-------------------------------------------------------------------- +# extraLabels + +@test "tlsInit/Job: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/tls-init-job.yaml \ + --set 'global.tls.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "tlsInit/Job: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/tls-init-job.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "tlsInit/Job: multiple extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/tls-init-job.yaml \ + --set 'global.tls.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/test/unit/webhook-cert-manager-deployment.bats b/charts/consul/test/unit/webhook-cert-manager-deployment.bats index 71d2e35c3a..cda0b25d68 100644 --- a/charts/consul/test/unit/webhook-cert-manager-deployment.bats +++ b/charts/consul/test/unit/webhook-cert-manager-deployment.bats @@ -109,3 +109,50 @@ load _helpers --set 'global.secretsBackend.vault.consulCARole=test2' \ . } + +#-------------------------------------------------------------------- +# extraLabels + +@test "webhookCertManager/Deployment: no extra labels defined by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/webhook-cert-manager-deployment.yaml \ + --set 'controller.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -r '.spec.template.metadata.labels | del(."app") | del(."chart") | del(."release") | del(."component") | del(."heritage")' | tee /dev/stderr) + [ "${actual}" = "{}" ] +} + +@test "webhookCertManager/Deployment: extra global labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/webhook-cert-manager-deployment.yaml \ + --set 'controller.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + . | tee /dev/stderr) + local actualBar=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + [ "${actualBar}" = "bar" ] + local actualTemplateBar=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + [ "${actualTemplateBar}" = "bar" ] +} + +@test "webhookCertManager/Deployment: multiple global extra labels can be set" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/webhook-cert-manager-deployment.yaml \ + --set 'controller.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.extraLabels.foo=bar' \ + --set 'global.extraLabels.baz=qux' \ + . | tee /dev/stderr) + local actualFoo=$(echo "${actual}" | yq -r '.metadata.labels.foo' | tee /dev/stderr) + local actualBaz=$(echo "${actual}" | yq -r '.metadata.labels.baz' | tee /dev/stderr) + [ "${actualFoo}" = "bar" ] + [ "${actualBaz}" = "qux" ] + local actualTemplateFoo=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.foo' | tee /dev/stderr) + local actualTemplateBaz=$(echo "${actual}" | yq -r '.spec.template.metadata.labels.baz' | tee /dev/stderr) + [ "${actualTemplateFoo}" = "bar" ] + [ "${actualTemplateBaz}" = "qux" ] +} diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index f36ebe6fb0..ccc7ea03c2 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -659,6 +659,19 @@ global: # the API before cancelling the request. consulAPITimeout: 5s + # Extra labels to attach to all pods, deployments, daemonsets, statefulsets, and jobs. This should be a YAML map. + # + # Example: + # + # ```yaml + # extraLabels: + # labelKey: label-value + # anotherLabelKey: another-label-value + # ``` + # + # @type: map + extraLabels: {} + # Server, when enabled, configures a server cluster to run. This should # be disabled if you plan on connecting to a Consul cluster external to # the Kube cluster. From 0bbb7b2437811b5a99311dc292e17522c9f47d5d Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Thu, 8 Dec 2022 13:04:34 -0800 Subject: [PATCH 190/235] Backport of Update CHANGELOG.md to describe change global.extraLabels into release/0.49.x (#1780) Co-authored-by: David Yu --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6037715f..6b54afb0d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +IMPROVEMENTS: +* Helm: + * Add a `global.extraLabels` stanza to allow setting global Kubernetes labels for all components deployed by the `consul-k8s` Helm chart. [[GH-1778](https://github.com/hashicorp/consul-k8s/pull/1778)] + ## 0.49.2 (December 1, 2022) IMPROVEMENTS: From 5c74d2687230573d9be51d4b3a77205f3592866e Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-ecosystem <82990057+hc-github-team-consul-ecosystem@users.noreply.github.com> Date: Mon, 19 Dec 2022 20:02:08 -0800 Subject: [PATCH 191/235] Backport of Ignore partition/namespace on SourceIntention list to match top-level compare logic into release/0.49.x (#1806) * backport of commit a2ba8916201af55cf2f57c8ed84506dcb1345aa9 * Add changelog note Co-authored-by: Kyle Havlovitz --- CHANGELOG.md | 4 ++++ control-plane/api/v1alpha1/serviceintentions_types.go | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b54afb0d8..ce2f6f5208 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ IMPROVEMENTS: * Helm: * Add a `global.extraLabels` stanza to allow setting global Kubernetes labels for all components deployed by the `consul-k8s` Helm chart. [[GH-1778](https://github.com/hashicorp/consul-k8s/pull/1778)] +BUG FIXES: +* Control Plane + * Don't incorrectly diff intention config entries when upgrading from Consul pre-1.12 to 1.12+ [[GH-1804](https://github.com/hashicorp/consul-k8s/pull/1804)] + ## 0.49.2 (December 1, 2022) IMPROVEMENTS: diff --git a/control-plane/api/v1alpha1/serviceintentions_types.go b/control-plane/api/v1alpha1/serviceintentions_types.go index 6488a3615c..a0a240639a 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types.go +++ b/control-plane/api/v1alpha1/serviceintentions_types.go @@ -239,7 +239,7 @@ func (in *ServiceIntentions) MatchesConsul(candidate api.ConfigEntry) bool { in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceIntentionsConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), - cmpopts.IgnoreFields(capi.SourceIntention{}, "LegacyID", "LegacyMeta", "LegacyCreateTime", "LegacyUpdateTime", "Precedence", "Type"), + cmpopts.IgnoreFields(capi.SourceIntention{}, "Partition", "Namespace", "LegacyID", "LegacyMeta", "LegacyCreateTime", "LegacyUpdateTime", "Precedence", "Type"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), // Consul will sort the sources by precedence when returning the resource From 7d691d5a30ecc3ef4b39f9fa680143103974500f Mon Sep 17 00:00:00 2001 From: David Yu Date: Tue, 20 Dec 2022 14:30:40 -0800 Subject: [PATCH 192/235] values.yaml - helm chart docs edits for 0.49.x (#1805) * helm chart docs edits Co-authored-by: Tu Nguyen --- charts/consul/values.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index ccc7ea03c2..199ff99edf 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -299,7 +299,7 @@ global: {} controller: - # Configuration to the Vault Secret that Kubernetes will use on + # Configuration to the Vault Secret that Kubernetes uses on # Kubernetes CRD creation, deletion, and update, to get TLS certificates # used issued from vault to send webhooks to the controller. tlsCert: @@ -308,7 +308,7 @@ global: # @type: string secretName: null - # Configuration to the Vault Secret that Kubernetes will use on + # Configuration to the Vault Secret that Kubernetes uses on # Kubernetes CRD creation, deletion, and update, to get CA certificates # used issued from vault to send webhooks to the controller. caCert: @@ -318,7 +318,7 @@ global: secretName: null connectInject: - # Configuration to the Vault Secret that Kubernetes will use on + # Configuration to the Vault Secret that Kubernetes uses on # Kubernetes pod creation, deletion, and update, to get CA certificates # used issued from vault to send webhooks to the ConnectInject. caCert: @@ -327,7 +327,7 @@ global: # @type: string secretName: null - # Configuration to the Vault Secret that Kubernetes will use on + # Configuration to the Vault Secret that Kubernetes uses on # Kubernetes pod creation, deletion, and update, to get TLS certificates # used issued from vault to send webhooks to the ConnectInject. tlsCert: @@ -655,7 +655,7 @@ global: # its components on OpenShift. enabled: false - # The time in seconds that the consul API client will wait for a response from + # The time in seconds that the consul API client waits for a response from # the API before cancelling the request. consulAPITimeout: 5s @@ -776,7 +776,7 @@ server: # storage classes, the PersistentVolumeClaims would need to be manually created. # A `null` value will use the Kubernetes cluster's default StorageClass. If a default # StorageClass does not exist, you will need to create one. - # Refer to the [Read/Write Tuning](https://www.consul.io/docs/install/performance#read-write-tuning) + # Refer to the [Read/Write Tuning](https://developer.hashicorp.com/consul/docs/install/performance#read-write-tuning) # section of the Server Performance Requirements documentation for considerations # around choosing a performant storage class. # @@ -869,9 +869,9 @@ server: # This configures the PodDisruptionBudget (https://kubernetes.io/docs/tasks/run-application/configure-pdb/) # for the server cluster. disruptionBudget: - # This will enable/disable registering a PodDisruptionBudget for the server - # cluster. If this is enabled, it will only register the budget so long as - # the server cluster is enabled. + # Enables registering a PodDisruptionBudget for the server + # cluster. If enabled, it only registers the budget so long as + # the server cluster is enabled. To disable, set to `false`. enabled: true # The maximum number of unavailable pods. By default, this will be @@ -1969,7 +1969,7 @@ connectInject: # Configures consul-cni plugin for Consul Service mesh services cni: - # If true, then all traffic redirection setup will use the consul-cni plugin. + # If true, then all traffic redirection setup uses the consul-cni plugin. # Requires connectInject.enabled to also be true. # @type: boolean enabled: false @@ -2969,9 +2969,9 @@ apiGateway: # @type: string nodeSelector: null - # This value defines the tolerations that will be assigned to a gateway pod. + # Toleration settings for gateway pods created with the managed gateway class. # This should be a multi-line string matching the - # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + # [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. # # @type: string tolerations: null From 92bbe6bc20cad3b1adef799e4d2e1f162d493f17 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Fri, 13 Jan 2023 12:14:56 -0500 Subject: [PATCH 193/235] Create annotation to allows users to use proxy health check (#1824) (#1830) --- CHANGELOG.md | 2 ++ control-plane/connect-inject/annotations.go | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce2f6f5208..3ecbe9ed66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ IMPROVEMENTS: * Helm: * Add a `global.extraLabels` stanza to allow setting global Kubernetes labels for all components deployed by the `consul-k8s` Helm chart. [[GH-1778](https://github.com/hashicorp/consul-k8s/pull/1778)] +* Control-Plane + * Add support for the annotation `consul.hashicorp.com/use-proxy-health-check`. [[GH-1824](https://github.com/hashicorp/consul-k8s/pull/1824)] BUG FIXES: * Control Plane diff --git a/control-plane/connect-inject/annotations.go b/control-plane/connect-inject/annotations.go index fa35959160..e63a7b1935 100644 --- a/control-plane/connect-inject/annotations.go +++ b/control-plane/connect-inject/annotations.go @@ -78,6 +78,11 @@ const ( // Deprecated: This annotation is no longer supported. annotationSyncPeriod = "consul.hashicorp.com/connect-sync-period" + // annotationUseProxyHealthCheck creates a readiness listener on the sidecar proxy and + // queries this instead of the application health check for the status of the application. + // Enable this only if the application does not support health checks. + annotationUseProxyHealthCheck = "consul.hashicorp.com/use-proxy-health-check" + // annotations for sidecar proxy resource limits. annotationSidecarProxyCPULimit = "consul.hashicorp.com/sidecar-proxy-cpu-limit" annotationSidecarProxyCPURequest = "consul.hashicorp.com/sidecar-proxy-cpu-request" From 3aac8e493d95dcd185e088e05c23db0b9d1ad3e7 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Tue, 17 Jan 2023 15:51:00 -0500 Subject: [PATCH 194/235] Add health checks for services that are synced (#1821) (#1839) * Add health checks for services that are synced - When the type of the service is ClusterIP, a health check will be added to the catalog registration with the health info of the service based on the state of the readiness probe of the pod associated with the service. - Replace `apiv1` with `corev1` to be consistent across the project. - Run `go mod tidy`. --- CHANGELOG.md | 1 + acceptance/tests/sync/sync_catalog_test.go | 8 ++- control-plane/catalog/to-consul/resource.go | 67 ++++++++++++------- .../catalog/to-consul/resource_test.go | 38 +++++++++++ control-plane/go.mod | 2 - control-plane/go.sum | 2 - 6 files changed, 90 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ecbe9ed66..08aaf16bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ IMPROVEMENTS: * Add a `global.extraLabels` stanza to allow setting global Kubernetes labels for all components deployed by the `consul-k8s` Helm chart. [[GH-1778](https://github.com/hashicorp/consul-k8s/pull/1778)] * Control-Plane * Add support for the annotation `consul.hashicorp.com/use-proxy-health-check`. [[GH-1824](https://github.com/hashicorp/consul-k8s/pull/1824)] + * Add health check for synced services based on the status of the Kubernetes readiness probe on synced pod. [[GH-1821](https://github.com/hashicorp/consul-k8s/pull/1821)] BUG FIXES: * Control Plane diff --git a/acceptance/tests/sync/sync_catalog_test.go b/acceptance/tests/sync/sync_catalog_test.go index 942843d53f..b43ef66099 100644 --- a/acceptance/tests/sync/sync_catalog_test.go +++ b/acceptance/tests/sync/sync_catalog_test.go @@ -9,6 +9,7 @@ import ( "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" "github.com/hashicorp/consul-k8s/acceptance/framework/logger" + "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/stretchr/testify/require" ) @@ -84,8 +85,13 @@ func TestSyncCatalog(t *testing.T) { service, _, err := consulClient.Catalog().Service(syncedServiceName, "", nil) require.NoError(t, err) - require.Equal(t, 1, len(service)) + require.Len(t, service, 1) require.Equal(t, []string{"k8s"}, service[0].ServiceTags) + filter := fmt.Sprintf("ServiceID == %q", service[0].ServiceID) + healthChecks, _, err := consulClient.Health().Checks(syncedServiceName, &api.QueryOptions{Filter: filter}) + require.NoError(t, err) + require.Len(t, healthChecks, 1) + require.Equal(t, api.HealthPassing, healthChecks[0].Status) }) } } diff --git a/control-plane/catalog/to-consul/resource.go b/control-plane/catalog/to-consul/resource.go index 239e2f5db9..a8ba6d20bd 100644 --- a/control-plane/catalog/to-consul/resource.go +++ b/control-plane/catalog/to-consul/resource.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/consul-k8s/control-plane/namespaces" consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/go-hclog" - apiv1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" @@ -33,6 +33,12 @@ const ( ConsulK8SRefKind = "external-k8s-ref-kind" ConsulK8SRefValue = "external-k8s-ref-name" ConsulK8SNodeName = "external-k8s-node-name" + + // consulKubernetesCheckType is the type of health check in Consul for Kubernetes readiness status. + consulKubernetesCheckType = "kubernetes-readiness" + // consulKubernetesCheckName is the name of health check in Consul for Kubernetes readiness status. + consulKubernetesCheckName = "Kubernetes Readiness Check" + kubernetesSuccessReasonMsg = "Kubernetes health checks passing" ) type NodePortSyncType string @@ -131,11 +137,11 @@ type ServiceResource struct { // serviceMap holds services we should sync to Consul. Keys are the // in the form /. - serviceMap map[string]*apiv1.Service + serviceMap map[string]*corev1.Service // endpointsMap uses the same keys as serviceMap but maps to the endpoints // of each service. - endpointsMap map[string]*apiv1.Endpoints + endpointsMap map[string]*corev1.Endpoints // consulMap holds the services in Consul that we've registered from kube. // It's populated via Consul's API and lets us diff what is actually in @@ -157,7 +163,7 @@ func (t *ServiceResource) Informer() cache.SharedIndexInformer { return t.Client.CoreV1().Services(metav1.NamespaceAll).Watch(t.Ctx, options) }, }, - &apiv1.Service{}, + &corev1.Service{}, 0, cache.Indexers{}, ) @@ -166,7 +172,7 @@ func (t *ServiceResource) Informer() cache.SharedIndexInformer { // Upsert implements the controller.Resource interface. func (t *ServiceResource) Upsert(key string, raw interface{}) error { // We expect a Service. If it isn't a service then just ignore it. - service, ok := raw.(*apiv1.Service) + service, ok := raw.(*corev1.Service) if !ok { t.Log.Warn("upsert got invalid type", "raw", raw) return nil @@ -176,7 +182,7 @@ func (t *ServiceResource) Upsert(key string, raw interface{}) error { defer t.serviceLock.Unlock() if t.serviceMap == nil { - t.serviceMap = make(map[string]*apiv1.Service) + t.serviceMap = make(map[string]*corev1.Service) } if !t.shouldSync(service) { @@ -205,7 +211,7 @@ func (t *ServiceResource) Upsert(key string, raw interface{}) error { "err", err) } else { if t.endpointsMap == nil { - t.endpointsMap = make(map[string]*apiv1.Endpoints) + t.endpointsMap = make(map[string]*corev1.Endpoints) } t.endpointsMap[key] = endpoints t.Log.Debug("[ServiceResource.Upsert] adding service's endpoints to endpointsMap", "key", key, "service", service, "endpoints", endpoints) @@ -254,7 +260,7 @@ func (t *ServiceResource) Run(ch <-chan struct{}) { } // shouldSync returns true if resyncing should be enabled for the given service. -func (t *ServiceResource) shouldSync(svc *apiv1.Service) bool { +func (t *ServiceResource) shouldSync(svc *corev1.Service) bool { // Namespace logic // If in deny list, don't sync if t.DenyK8sNamespacesSet.Contains(svc.Namespace) { @@ -269,7 +275,7 @@ func (t *ServiceResource) shouldSync(svc *apiv1.Service) bool { } // Ignore ClusterIP services if ClusterIP sync is disabled - if svc.Spec.Type == apiv1.ServiceTypeClusterIP && !t.ClusterIPSync { + if svc.Spec.Type == corev1.ServiceTypeClusterIP && !t.ClusterIPSync { t.Log.Debug("[shouldSync] ignoring clusterip service", "svc.Namespace", svc.Namespace, "service", svc) return false } @@ -310,9 +316,9 @@ func (t *ServiceResource) shouldTrackEndpoints(key string) bool { return false } - return svc.Spec.Type == apiv1.ServiceTypeNodePort || - svc.Spec.Type == apiv1.ServiceTypeClusterIP || - (t.LoadBalancerEndpointsSync && svc.Spec.Type == apiv1.ServiceTypeLoadBalancer) + return svc.Spec.Type == corev1.ServiceTypeNodePort || + svc.Spec.Type == corev1.ServiceTypeClusterIP || + (t.LoadBalancerEndpointsSync && svc.Spec.Type == corev1.ServiceTypeLoadBalancer) } // generateRegistrations generates the necessary Consul registrations for @@ -380,7 +386,7 @@ func (t *ServiceResource) generateRegistrations(key string) { var overridePortNumber int if len(svc.Spec.Ports) > 0 { var port int - isNodePort := svc.Spec.Type == apiv1.ServiceTypeNodePort + isNodePort := svc.Spec.Type == corev1.ServiceTypeNodePort // If a specific port is specified, then use that port value portAnnotation, ok := svc.Annotations[annotationServicePort] @@ -479,7 +485,7 @@ func (t *ServiceResource) generateRegistrations(key string) { // each LoadBalancer entry. We only support entries that have an IP // address assigned (not hostnames). // If LoadBalancerEndpointsSync is true sync LB endpoints instead of loadbalancer ingress. - case apiv1.ServiceTypeLoadBalancer: + case corev1.ServiceTypeLoadBalancer: if t.LoadBalancerEndpointsSync { t.registerServiceInstance(baseNode, baseService, key, overridePortName, overridePortNumber, false) } else { @@ -512,7 +518,7 @@ func (t *ServiceResource) generateRegistrations(key string) { // endpoint of the service, which corresponds to the nodes the service's // pods are running on. This way we don't register _every_ K8S // node as part of the service. - case apiv1.ServiceTypeNodePort: + case corev1.ServiceTypeNodePort: if t.endpointsMap == nil { return } @@ -538,11 +544,11 @@ func (t *ServiceResource) generateRegistrations(key string) { } // Set the expected node address type - var expectedType apiv1.NodeAddressType + var expectedType corev1.NodeAddressType if t.NodePortSync == InternalOnly { - expectedType = apiv1.NodeInternalIP + expectedType = corev1.NodeInternalIP } else { - expectedType = apiv1.NodeExternalIP + expectedType = corev1.NodeExternalIP } // Find the ip address for the node and @@ -571,7 +577,7 @@ func (t *ServiceResource) generateRegistrations(key string) { // use an InternalIP if t.NodePortSync == ExternalFirst && !found { for _, address := range node.Status.Addresses { - if address.Type == apiv1.NodeInternalIP { + if address.Type == corev1.NodeInternalIP { r := baseNode rs := baseService r.Service = &rs @@ -593,7 +599,7 @@ func (t *ServiceResource) generateRegistrations(key string) { // For ClusterIP services, we register a service instance // for each endpoint. - case apiv1.ServiceTypeClusterIP: + case corev1.ServiceTypeClusterIP: t.registerServiceInstance(baseNode, baseService, key, overridePortName, overridePortNumber, true) } } @@ -674,6 +680,16 @@ func (t *ServiceResource) registerServiceInstance( r.Service.Meta[ConsulK8SNodeName] = *subsetAddr.NodeName } + r.Check = &consulapi.AgentCheck{ + CheckID: consulHealthCheckID(endpoints.Namespace, serviceID(r.Service.Service, addr)), + Name: consulKubernetesCheckName, + Namespace: baseService.Namespace, + Type: consulKubernetesCheckType, + Status: consulapi.HealthPassing, + ServiceID: serviceID(r.Service.Service, addr), + Output: kubernetesSuccessReasonMsg, + } + t.consulMap[key] = append(t.consulMap[key], &r) } } @@ -723,7 +739,7 @@ func (t *serviceEndpointsResource) Informer() cache.SharedIndexInformer { Watch(t.Ctx, options) }, }, - &apiv1.Endpoints{}, + &corev1.Endpoints{}, 0, cache.Indexers{}, ) @@ -731,7 +747,7 @@ func (t *serviceEndpointsResource) Informer() cache.SharedIndexInformer { func (t *serviceEndpointsResource) Upsert(key string, raw interface{}) error { svc := t.Service - endpoints, ok := raw.(*apiv1.Endpoints) + endpoints, ok := raw.(*corev1.Endpoints) if !ok { svc.Log.Warn("upsert got invalid type", "raw", raw) return nil @@ -747,7 +763,7 @@ func (t *serviceEndpointsResource) Upsert(key string, raw interface{}) error { // We are tracking this service so let's keep track of the endpoints if svc.endpointsMap == nil { - svc.endpointsMap = make(map[string]*apiv1.Endpoints) + svc.endpointsMap = make(map[string]*corev1.Endpoints) } svc.endpointsMap[key] = endpoints @@ -788,3 +804,8 @@ func (t *ServiceResource) addPrefixAndK8SNamespace(name, namespace string) strin return name } + +// consulHealthCheckID deterministically generates a health check ID based on service ID and Kubernetes namespace. +func consulHealthCheckID(k8sNS string, serviceID string) string { + return fmt.Sprintf("%s/%s", k8sNS, serviceID) +} diff --git a/control-plane/catalog/to-consul/resource_test.go b/control-plane/catalog/to-consul/resource_test.go index 28335dea27..9ba94123ef 100644 --- a/control-plane/catalog/to-consul/resource_test.go +++ b/control-plane/catalog/to-consul/resource_test.go @@ -6,6 +6,7 @@ import ( mapset "github.com/deckarep/golang-set" "github.com/hashicorp/consul-k8s/control-plane/helper/controller" + consulapi "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil/retry" "github.com/hashicorp/go-hclog" "github.com/stretchr/testify/require" @@ -1005,6 +1006,43 @@ func TestServiceResource_clusterIP(t *testing.T) { }) } +// Test that the proper registrations with health checks are generated for a ClusterIP type. +func TestServiceResource_clusterIP_healthCheck(t *testing.T) { + t.Parallel() + client := fake.NewSimpleClientset() + syncer := newTestSyncer() + serviceResource := defaultServiceResource(client, syncer) + serviceResource.ClusterIPSync = true + + // Start the controller + closer := controller.TestControllerRun(&serviceResource) + defer closer() + + // Insert the service + svc := clusterIPService("foo", metav1.NamespaceDefault) + _, err := client.CoreV1().Services(metav1.NamespaceDefault).Create(context.Background(), svc, metav1.CreateOptions{}) + require.NoError(t, err) + + // Insert the endpoints + createEndpoints(t, client, "foo", metav1.NamespaceDefault) + + // Verify what we got + retry.Run(t, func(r *retry.R) { + syncer.Lock() + defer syncer.Unlock() + actual := syncer.Registrations + require.Len(r, actual, 2) + require.Equal(r, consulKubernetesCheckName, actual[0].Check.Name) + require.Equal(r, consulapi.HealthPassing, actual[0].Check.Status) + require.Equal(r, kubernetesSuccessReasonMsg, actual[0].Check.Output) + require.Equal(r, consulKubernetesCheckType, actual[0].Check.Type) + require.Equal(r, consulKubernetesCheckName, actual[1].Check.Name) + require.Equal(r, consulapi.HealthPassing, actual[1].Check.Status) + require.Equal(r, kubernetesSuccessReasonMsg, actual[1].Check.Output) + require.Equal(r, consulKubernetesCheckType, actual[1].Check.Type) + }) +} + // Test clusterIP with prefix. func TestServiceResource_clusterIPPrefix(t *testing.T) { t.Parallel() diff --git a/control-plane/go.mod b/control-plane/go.mod index d3c6106eac..8dd66de28d 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -9,13 +9,11 @@ require ( github.com/google/go-cmp v0.5.7 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af65262de8 - github.com/hashicorp/consul-server-connection-manager v0.0.0-20220922180412-01c5be1c636f github.com/hashicorp/consul/api v1.10.1-0.20221005170644-13da2c5fad69 github.com/hashicorp/consul/sdk v0.11.0 github.com/hashicorp/go-discover v0.0.0-20200812215701-c4b85f6ed31f github.com/hashicorp/go-hclog v1.2.2 github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/go-rootcerts v1.0.2 github.com/hashicorp/serf v0.10.1 github.com/kr/text v0.2.0 github.com/miekg/dns v1.1.41 diff --git a/control-plane/go.sum b/control-plane/go.sum index f281ffad23..54a0604111 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -344,8 +344,6 @@ github.com/hashicorp/consul-k8s/control-plane/cni v0.0.0-20220831174802-b8af6526 github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.10.1-0.20221005170644-13da2c5fad69 h1:IALuDSO0f6x0txq/tjUDF3sShyDMT8dmjn9af6Ik8BA= github.com/hashicorp/consul/api v1.10.1-0.20221005170644-13da2c5fad69/go.mod h1:T09kWtKqm8j1S9yTd1r0hVhfOyPrvLb0zb6dPKpNXxQ= -github.com/hashicorp/consul/proto-public v0.1.0 h1:O0LSmCqydZi363hsqc6n2v5sMz3usQMXZF6ziK3SzXU= -github.com/hashicorp/consul/proto-public v0.1.0/go.mod h1:vs2KkuWwtjkIgA5ezp4YKPzQp4GitV+q/+PvksrA92k= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4= github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw= From 53545d675c0ac61d2cb0b423ae96c5cade0ea928 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Mon, 23 Jan 2023 14:16:56 -0500 Subject: [PATCH 195/235] Use Proxy Healthchecks when configured. (#1843) - When a service is configured with the correct annotation, a readiness endpoint with be configured in Consul dataplane, and the readiness probe of the sidecar will be configured to use that endpoint to determine the health of the system. Additionally, when t-proxy is enabled, that port shall be in the ExcludeList for inbound connections. --- CHANGELOG.md | 2 +- .../connect-inject/container_init.go | 15 ++++ .../connect-inject/container_init_test.go | 88 ++++++++++++++++++- .../connect-inject/endpoints_controller.go | 35 ++++++-- .../endpoints_controller_test.go | 82 +++++++++++++++++ control-plane/connect-inject/envoy_sidecar.go | 23 ++++- .../connect-inject/envoy_sidecar_test.go | 50 ++++++++--- .../connect-inject/redirect_traffic.go | 6 ++ .../connect-inject/redirect_traffic_test.go | 33 +++++++ 9 files changed, 315 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08aaf16bbc..d9cc5e4aa7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ IMPROVEMENTS: * Helm: * Add a `global.extraLabels` stanza to allow setting global Kubernetes labels for all components deployed by the `consul-k8s` Helm chart. [[GH-1778](https://github.com/hashicorp/consul-k8s/pull/1778)] * Control-Plane - * Add support for the annotation `consul.hashicorp.com/use-proxy-health-check`. [[GH-1824](https://github.com/hashicorp/consul-k8s/pull/1824)] + * Add support for the annotation `consul.hashicorp.com/use-proxy-health-check`. When this annotation is used by a service, it configures a readiness endpoint on Consul Dataplane and queries it instead of the proxy's inbound port which forwards requests to the application. [[GH-1824](https://github.com/hashicorp/consul-k8s/pull/1824)], [[GH-1843](https://github.com/hashicorp/consul-k8s/pull/1843)] * Add health check for synced services based on the status of the Kubernetes readiness probe on synced pod. [[GH-1821](https://github.com/hashicorp/consul-k8s/pull/1821)] BUG FIXES: diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index e0ef413011..47dabbbe0b 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -56,6 +56,12 @@ type initContainerCommandData struct { // EnvoyUID is the Linux user id that will be used when tproxy is enabled. EnvoyUID int + // EnableProxyHealthChecks configures a readiness endpoint on the envoy sidecar. + EnableProxyHealthChecks bool + // EnableProxyHealthChecks is the port on which the readiness endpoint is configured + // on the envoy sidecar. + EnvoyHealthCheckPort int + // EnableTransparentProxy configures this init container to run in transparent proxy mode, // i.e. run consul connect redirect-traffic command and add the required privileges to the // container to do that. @@ -166,6 +172,8 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, ConsulCACert: w.ConsulCACert, EnableTransparentProxy: tproxyEnabled, EnableCNI: w.EnableCNI, + EnableProxyHealthChecks: useProxyHealthCheck(pod), + EnvoyHealthCheckPort: proxyDefaultHealthPort + mpi.serviceIndex, TProxyExcludeInboundPorts: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeInboundPorts, pod), TProxyExcludeOutboundPorts: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundPorts, pod), TProxyExcludeOutboundCIDRs: splitCommaSeparatedItemsFromAnnotation(annotationTProxyExcludeOutboundCIDRs, pod), @@ -436,6 +444,10 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD {{- else }} -proxy-id="$(cat /consul/connect-inject/proxyid)" \ {{- end }} + {{- if .EnableProxyHealthChecks }} + -envoy-ready-bind-address="${POD_IP}" \ + -envoy-ready-bind-port={{ .EnvoyHealthCheckPort }} \ + {{- end }} {{- if .PrometheusScrapePath }} -prometheus-scrape-path="{{ .PrometheusScrapePath }}" \ {{- end }} @@ -498,6 +510,9 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD {{- range .TProxyExcludeOutboundPorts }} -exclude-outbound-port="{{ . }}" \ {{- end }} + {{- if .EnableProxyHealthChecks }} + -exclude-inbound-port={{ .EnvoyHealthCheckPort }} \ + {{- end }} {{- range .TProxyExcludeOutboundCIDRs }} -exclude-outbound-cidr="{{ . }}" \ {{- end }} diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index 22f14c1f73..f4ab3eed47 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -74,7 +74,29 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD "", "", }, + { + "Proxy Health Checks", + func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[annotationService] = "web" + pod.Annotations[annotationUseProxyHealthCheck] = "true" + return pod + }, + MeshWebhook{}, + `/bin/sh -ec +export CONSUL_HTTP_ADDR="${HOST_IP}:8500" +export CONSUL_GRPC_ADDR="${HOST_IP}:8502" +consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ + -consul-api-timeout=0s \ +# Generate the envoy bootstrap code +/consul/connect-inject/consul connect envoy \ + -proxy-id="$(cat /consul/connect-inject/proxyid)" \ + -envoy-ready-bind-address="${POD_IP}" \ + -envoy-ready-bind-port=21000 \ + -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + "", + "", + }, { "When auth method is set -service-account-name and -service-name are passed in", func(pod *corev1.Pod) *corev1.Pod { @@ -384,7 +406,6 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { -proxy-uid=5995`, map[string]string{keyTransparentProxy: "true"}, }, - "enabled globally, ns not set, annotation not set, cni enabled": { true, true, @@ -395,6 +416,17 @@ func TestHandlerContainerInit_transparentProxy(t *testing.T) { -proxy-uid=5995`, nil, }, + "enabled globally, ns not set, annotation is true, cni disabled, proxy health checks": { + true, + false, + map[string]string{keyTransparentProxy: "true", annotationUseProxyHealthCheck: "true"}, + `/consul/connect-inject/consul connect redirect-traffic \ + -exclude-inbound-port=21000 \ + -proxy-id="$(cat /consul/connect-inject/proxyid)" \ + -proxy-uid=5995`, + "", + nil, + }, } for name, c := range cases { t.Run(name, func(t *testing.T) { @@ -995,6 +1027,60 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD /consul/connect-inject/consul connect envoy \ -proxy-id="$(cat /consul/connect-inject/proxyid-web-admin)" \ -admin-bind=127.0.0.1:19001 \ + -bootstrap > /consul/connect-inject/envoy-bootstrap-web-admin.yaml`, + }, + }, + { + "Whole template, multiport, proxy health check", + func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[annotationUseProxyHealthCheck] = "true" + return pod + }, + MeshWebhook{ConsulAPITimeout: 5 * time.Second}, + 2, + []multiPortInfo{ + { + serviceIndex: 0, + serviceName: "web", + }, + { + serviceIndex: 1, + serviceName: "web-admin", + }, + }, + []string{ + `/bin/sh -ec +export CONSUL_HTTP_ADDR="${HOST_IP}:8500" +export CONSUL_GRPC_ADDR="${HOST_IP}:8502" +consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ + -consul-api-timeout=5s \ + -multiport=true \ + -proxy-id-file=/consul/connect-inject/proxyid-web \ + -service-name="web" \ + +# Generate the envoy bootstrap code +/consul/connect-inject/consul connect envoy \ + -proxy-id="$(cat /consul/connect-inject/proxyid-web)" \ + -envoy-ready-bind-address="${POD_IP}" \ + -envoy-ready-bind-port=21000 \ + -admin-bind=127.0.0.1:19000 \ + -bootstrap > /consul/connect-inject/envoy-bootstrap-web.yaml`, + + `/bin/sh -ec +export CONSUL_HTTP_ADDR="${HOST_IP}:8500" +export CONSUL_GRPC_ADDR="${HOST_IP}:8502" +consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD_NAMESPACE} \ + -consul-api-timeout=5s \ + -multiport=true \ + -proxy-id-file=/consul/connect-inject/proxyid-web-admin \ + -service-name="web-admin" \ + +# Generate the envoy bootstrap code +/consul/connect-inject/consul connect envoy \ + -proxy-id="$(cat /consul/connect-inject/proxyid-web-admin)" \ + -envoy-ready-bind-address="${POD_IP}" \ + -envoy-ready-bind-port=21001 \ + -admin-bind=127.0.0.1:19001 \ -bootstrap > /consul/connect-inject/envoy-bootstrap-web-admin.yaml`, }, }, diff --git a/control-plane/connect-inject/endpoints_controller.go b/control-plane/connect-inject/endpoints_controller.go index 9b37ca3bcf..f9759b4fe7 100644 --- a/control-plane/connect-inject/endpoints_controller.go +++ b/control-plane/connect-inject/endpoints_controller.go @@ -61,6 +61,9 @@ const ( // proxyDefaultInboundPort is the default inbound port for the proxy. proxyDefaultInboundPort = 20000 + + // proxyDefaultHealthPort is the default health check port for the proxy. + proxyDefaultHealthPort = 21000 ) type EndpointsController struct { @@ -501,6 +504,31 @@ func (r *EndpointsController) createServiceRegistrations(pod corev1.Pod, service if idx := getMultiPortIdx(pod, serviceEndpoints); idx >= 0 { proxyPort += idx } + var publicListenerCheck api.AgentServiceCheck + if useProxyHealthCheck(pod) { + // When using the proxy's health check, create an HTTP check on the ready endpoint + // that will be configured on the proxy sidecar container. + healthCheckPort := proxyDefaultHealthPort + if idx := getMultiPortIdx(pod, serviceEndpoints); idx >= 0 { + healthCheckPort += idx + } + publicListenerCheck = api.AgentServiceCheck{ + Name: "Proxy Public Listener", + HTTP: fmt.Sprintf("http://%s:%d/ready", pod.Status.PodIP, healthCheckPort), + TLSSkipVerify: true, + Interval: "10s", + DeregisterCriticalServiceAfter: "10m", + } + } else { + // Configure the default application health check. + publicListenerCheck = api.AgentServiceCheck{ + Name: "Proxy Public Listener", + TCP: fmt.Sprintf("%s:%d", pod.Status.PodIP, proxyPort), + Interval: "10s", + DeregisterCriticalServiceAfter: "10m", + } + } + proxyService := &api.AgentServiceRegistration{ Kind: api.ServiceKindConnectProxy, ID: proxyServiceID, @@ -511,12 +539,7 @@ func (r *EndpointsController) createServiceRegistrations(pod corev1.Pod, service Namespace: r.consulNamespace(pod.Namespace), Proxy: proxyConfig, Checks: api.AgentServiceChecks{ - { - Name: "Proxy Public Listener", - TCP: fmt.Sprintf("%s:%d", pod.Status.PodIP, proxyPort), - Interval: "10s", - DeregisterCriticalServiceAfter: "10m", - }, + &publicListenerCheck, { Name: "Destination Alias", AliasService: serviceID, diff --git a/control-plane/connect-inject/endpoints_controller_test.go b/control-plane/connect-inject/endpoints_controller_test.go index 49ee67a91d..ce76d1fa49 100644 --- a/control-plane/connect-inject/endpoints_controller_test.go +++ b/control-plane/connect-inject/endpoints_controller_test.go @@ -1187,6 +1187,7 @@ func TestReconcileCreateEndpoint(t *testing.T) { expectedProxySvcInstances []*api.CatalogService expectedAgentHealthChecks []*api.AgentCheck expErr string + useProxyHealthChecks bool }{ { name: "Empty endpoints", @@ -1279,6 +1280,76 @@ func TestReconcileCreateEndpoint(t *testing.T) { }, }, }, + { + name: "Basic endpoints with proxy healthchecks", + useProxyHealthChecks: true, + consulSvcName: "service-created", + k8sObjects: func() []runtime.Object { + pod1 := createPod("pod1", "1.2.3.4", true, true) + pod1.Annotations[annotationUseProxyHealthCheck] = "true" + endpoint := &corev1.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Name: "service-created", + Namespace: "default", + }, + Subsets: []corev1.EndpointSubset{ + { + Addresses: []corev1.EndpointAddress{ + { + IP: "1.2.3.4", + NodeName: &nodeName, + TargetRef: &corev1.ObjectReference{ + Kind: "Pod", + Name: "pod1", + Namespace: "default", + }, + }, + }, + }, + }, + } + return []runtime.Object{pod1, endpoint} + }, + initialConsulSvcs: []*api.AgentServiceRegistration{}, + expectedNumSvcInstances: 1, + expectedConsulSvcInstances: []*api.CatalogService{ + { + ServiceID: "pod1-service-created", + ServiceName: "service-created", + ServiceAddress: "1.2.3.4", + ServicePort: 0, + ServiceMeta: map[string]string{MetaKeyPodName: "pod1", MetaKeyKubeServiceName: "service-created", MetaKeyKubeNS: "default", MetaKeyManagedBy: managedByValue}, + ServiceTags: []string{}, + }, + }, + expectedProxySvcInstances: []*api.CatalogService{ + { + ServiceID: "pod1-service-created-sidecar-proxy", + ServiceName: "service-created-sidecar-proxy", + ServiceAddress: "1.2.3.4", + ServicePort: 20000, + ServiceProxy: &api.AgentServiceConnectProxyConfig{ + DestinationServiceName: "service-created", + DestinationServiceID: "pod1-service-created", + LocalServiceAddress: "", + LocalServicePort: 0, + }, + ServiceMeta: map[string]string{MetaKeyPodName: "pod1", MetaKeyKubeServiceName: "service-created", MetaKeyKubeNS: "default", MetaKeyManagedBy: managedByValue}, + ServiceTags: []string{}, + }, + }, + expectedAgentHealthChecks: []*api.AgentCheck{ + { + CheckID: "default/pod1-service-created/kubernetes-health-check", + ServiceName: "service-created", + ServiceID: "pod1-service-created", + Name: "Kubernetes Health Check", + Status: api.HealthPassing, + Output: kubernetesSuccessReasonMsg, + Type: ttl, + }, + }, + }, { name: "Endpoints with multiple addresses", consulSvcName: "service-created", @@ -1811,6 +1882,17 @@ func TestReconcileCreateEndpoint(t *testing.T) { require.Contains(t, expectedChecks, checks[0].Name) require.Contains(t, expectedChecks, checks[1].Name) } + agentChecks, err := consulClient.Agent().Checks() + require.NoError(t, err) + for _, check := range agentChecks { + if check.Name == "Proxy Public Listener" { + if tt.useProxyHealthChecks { + require.Equal(t, "http", check.Type) + } else { + require.Equal(t, "tcp", check.Type) + } + } + } // Check that the Consul health check was created for the k8s pod. if tt.expectedAgentHealthChecks != nil { diff --git a/control-plane/connect-inject/envoy_sidecar.go b/control-plane/connect-inject/envoy_sidecar.go index 7bf55afe60..53b3fcac55 100644 --- a/control-plane/connect-inject/envoy_sidecar.go +++ b/control-plane/connect-inject/envoy_sidecar.go @@ -50,6 +50,14 @@ func (w *MeshWebhook) envoySidecar(namespace corev1.Namespace, pod corev1.Pod, m Command: cmd, } + if useProxyHealthCheck(pod) { + // Add a port on the sidecar where the sidecar proxy will be queried for its health. + container.Ports = append(container.Ports, corev1.ContainerPort{ + Name: fmt.Sprintf("%s-%d", "proxy-health", mpi.serviceIndex), + ContainerPort: int32(proxyDefaultHealthPort + mpi.serviceIndex), + }) + } + // Add any extra Envoy VolumeMounts. if _, ok := pod.Annotations[annotationConsulSidecarUserVolumeMount]; ok { var volumeMount []corev1.VolumeMount @@ -105,7 +113,7 @@ func (w *MeshWebhook) getContainerSidecarCommand(pod corev1.Pod, multiPortSvcNam } if multiPortSvcName != "" { // --base-id is needed so multiple Envoy proxies can run on the same host. - cmd = append(cmd, "--base-id", fmt.Sprintf("%d", multiPortSvcIdx)) + cmd = append(cmd, "--base-id", strconv.Itoa(multiPortSvcIdx)) } // Check to see if the user has overriden concurrency via an annotation. @@ -215,3 +223,16 @@ func (w *MeshWebhook) envoySidecarResources(pod corev1.Pod) (corev1.ResourceRequ return resources, nil } + +// useProxyHealthCheck returns true if the pod has the annotation 'consul.hashicorp.com/use-proxy-health-check' +// set to truthy values. +func useProxyHealthCheck(pod corev1.Pod) bool { + if v, ok := pod.Annotations[annotationUseProxyHealthCheck]; ok { + useProxyHealthCheck, err := strconv.ParseBool(v) + if err != nil { + return false + } + return useProxyHealthCheck + } + return false +} diff --git a/control-plane/connect-inject/envoy_sidecar_test.go b/control-plane/connect-inject/envoy_sidecar_test.go index cd83d74244..43c464ed7f 100644 --- a/control-plane/connect-inject/envoy_sidecar_test.go +++ b/control-plane/connect-inject/envoy_sidecar_test.go @@ -12,10 +12,10 @@ import ( ) func TestHandlerEnvoySidecar(t *testing.T) { - require := require.New(t) cases := map[string]struct { annotations map[string]string expCommand []string + expPort *corev1.ContainerPort expErr string }{ "default settings, no annotations": { @@ -39,6 +39,21 @@ func TestHandlerEnvoySidecar(t *testing.T) { "--concurrency", "42", }, }, + "default settings, proxy health check annotations": { + annotations: map[string]string{ + annotationService: "foo", + annotationUseProxyHealthCheck: "true", + }, + expCommand: []string{ + "envoy", + "--config-path", "/consul/connect-inject/envoy-bootstrap.yaml", + "--concurrency", "0", + }, + expPort: &corev1.ContainerPort{ + Name: "proxy-health-0", + ContainerPort: int32(proxyDefaultHealthPort), + }, + }, "default settings, invalid concurrency annotation negative number": { annotations: map[string]string{ annotationService: "foo", @@ -64,28 +79,31 @@ func TestHandlerEnvoySidecar(t *testing.T) { } container, err := h.envoySidecar(testNS, pod, multiPortInfo{}) if c.expErr != "" { - require.Contains(err.Error(), c.expErr) + require.Contains(t, err.Error(), c.expErr) } else { - require.NoError(err) - require.Equal(c.expCommand, container.Command) - require.Equal(container.VolumeMounts, []corev1.VolumeMount{ + require.NoError(t, err) + require.Equal(t, c.expCommand, container.Command) + require.Equal(t, container.VolumeMounts, []corev1.VolumeMount{ { Name: volumeName, MountPath: "/consul/connect-inject", }, }) + if c.expPort != nil { + require.Contains(t, container.Ports, *c.expPort) + } } }) } } func TestHandlerEnvoySidecar_Multiport(t *testing.T) { - require := require.New(t) w := MeshWebhook{} pod := corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Annotations: map[string]string{ - annotationService: "web,web-admin", + annotationService: "web,web-admin", + annotationUseProxyHealthCheck: "true", }, }, @@ -114,17 +132,29 @@ func TestHandlerEnvoySidecar_Multiport(t *testing.T) { 0: {"envoy", "--config-path", "/consul/connect-inject/envoy-bootstrap-web.yaml", "--base-id", "0", "--concurrency", "0"}, 1: {"envoy", "--config-path", "/consul/connect-inject/envoy-bootstrap-web-admin.yaml", "--base-id", "1", "--concurrency", "0"}, } + expPorts := map[int]corev1.ContainerPort{ + 0: { + Name: "proxy-health-0", + ContainerPort: int32(proxyDefaultHealthPort), + }, + 1: { + Name: "proxy-health-1", + ContainerPort: int32(proxyDefaultHealthPort + 1), + }, + } for i := 0; i < 2; i++ { container, err := w.envoySidecar(testNS, pod, multiPortInfos[i]) - require.NoError(err) - require.Equal(expCommand[i], container.Command) + require.NoError(t, err) + require.Equal(t, expCommand[i], container.Command) - require.Equal(container.VolumeMounts, []corev1.VolumeMount{ + require.Equal(t, container.VolumeMounts, []corev1.VolumeMount{ { Name: volumeName, MountPath: "/consul/connect-inject", }, }) + + require.Contains(t, container.Ports, expPorts[i]) } } diff --git a/control-plane/connect-inject/redirect_traffic.go b/control-plane/connect-inject/redirect_traffic.go index 895b5befbe..71aebf54e7 100644 --- a/control-plane/connect-inject/redirect_traffic.go +++ b/control-plane/connect-inject/redirect_traffic.go @@ -44,6 +44,12 @@ func (w *MeshWebhook) addRedirectTrafficConfigAnnotation(pod *corev1.Pod, ns cor cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, prometheusScrapePort) } + // Exclude the port on which the proxy health check port will be configured if + // using the proxy health check for a service. + if useProxyHealthCheck(*pod) { + cfg.ExcludeInboundPorts = append(cfg.ExcludeInboundPorts, strconv.Itoa(proxyDefaultHealthPort)) + } + // Exclude any overwritten liveness/readiness/startup ports from redirection. overwriteProbes, err := shouldOverwriteProbes(*pod, w.TProxyOverwriteProbes) if err != nil { diff --git a/control-plane/connect-inject/redirect_traffic_test.go b/control-plane/connect-inject/redirect_traffic_test.go index 838f1c0c25..1478786be5 100644 --- a/control-plane/connect-inject/redirect_traffic_test.go +++ b/control-plane/connect-inject/redirect_traffic_test.go @@ -74,6 +74,39 @@ func TestAddRedirectTrafficConfig(t *testing.T) { ExcludeUIDs: []string{"5996"}, }, }, + { + name: "proxy health checks enabled", + webhook: MeshWebhook{ + Log: logrtest.TestLogger{T: t}, + AllowK8sNamespacesSet: mapset.NewSetWith("*"), + DenyK8sNamespacesSet: mapset.NewSet(), + decoder: decoder, + }, + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: defaultNamespace, + Name: defaultPodName, + Annotations: map[string]string{ + annotationUseProxyHealthCheck: "true", + }, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Name: "test", + }, + }, + }, + }, + expCfg: iptables.Config{ + ConsulDNSIP: "", + ProxyUserID: strconv.Itoa(envoyUserAndGroupID), + ProxyInboundPort: proxyDefaultInboundPort, + ProxyOutboundPort: iptables.DefaultTProxyOutboundPort, + ExcludeUIDs: []string{"5996"}, + ExcludeInboundPorts: []string{"21000"}, + }, + }, { name: "metrics enabled", webhook: MeshWebhook{ From 5bf1d1f313250c29d41645a5afaf02ba5dd86b7a Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Sun, 29 Jan 2023 20:15:07 -0500 Subject: [PATCH 196/235] Pre-release 0.49.3 (#1857) --- CHANGELOG.md | 2 +- charts/consul/Chart.yaml | 10 +++++----- charts/consul/values.yaml | 4 ++-- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9cc5e4aa7..3c607a8569 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.49.3 (January 30, 2023) IMPROVEMENTS: * Helm: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 5df9536f37..ed72f566b6 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul -version: 0.49.3-dev -appVersion: 1.13.4 +version: 0.49.3 +appVersion: 1.13.6 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: true + artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.13.4 + image: hashicorp/consul:1.13.6 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.3-dev + image: hashicorp/consul-k8s-control-plane:0.49.3 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 199ff99edf..a101e431d8 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -109,7 +109,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.13.4" + image: "hashicorp/consul:1.13.6" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.3-dev + imageK8S: hashicorp/consul-k8s-control-plane:0.49.3 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index c2a5437b2c..8dd84f084f 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index c2a5437b2c..8dd84f084f 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 9f440f54e443affb6433de124a06ad900b47ca4c Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Wed, 1 Feb 2023 09:47:35 -0500 Subject: [PATCH 197/235] set dev mode for 0.49.4 (#1859) --- CHANGELOG.md | 2 ++ charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c607a8569..a1ef65e7ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.49.3 (January 30, 2023) IMPROVEMENTS: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index ed72f566b6..6001345e96 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.3 +version: 0.49.4-dev appVersion: 1.13.6 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: false + artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.6 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.3 + image: hashicorp/consul-k8s-control-plane:0.49.4-dev - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index a101e431d8..3c296ff65e 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.3 + imageK8S: hashicorp/consul-k8s-control-plane:0.49.4-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 8dd84f084f..71d63e9061 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.3" + Version = "0.49.4" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 8dd84f084f..71d63e9061 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.3" + Version = "0.49.4" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 95e0f43c00f06e35aadf990bf28d11cbafe08b9d Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Thu, 2 Feb 2023 15:32:11 -0500 Subject: [PATCH 198/235] Exclude openebs namespace from injection. (#1869) (#1875) * Exclude openebs namespace from injection. OpenEBS is a Kubernetes storage solution. When you spin up a PVC, under the hood OpenEBS creates a pod to handle the necessary storage operations. If the openebs namespace is not excluded from injection, that pod can't start because our mutatingwebhook config requires all pod scheduling requests make it to our webhook and our webhook isn't running yet because the consul servers aren't running. This is a breaking change but I think it's worth it because it's very unlikely anyone is using the openebs namespace for anything other than openebs. * Changelog Co-authored-by: Luke Kysow <1034429+lkysow@users.noreply.github.com> --- CHANGELOG.md | 15 +++++++++++++++ charts/consul/values.yaml | 8 ++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1ef65e7ac..207bdcff3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ ## UNRELEASED +BREAKING CHANGES: +* Helm: + * Change defaults to exclude the `openebs` namespace from sidecar injection. If you previously had pods in that namespace + that you wanted to be injected, you must now set `namespaceSelector` as follows: + + ```yaml + connectInject: + namespaceSelector: | + matchExpressions: + - key: "kubernetes.io/metadata.name" + operator: "NotIn" + values: ["kube-system","local-path-storage"] + ``` + [[GH-1869](https://github.com/hashicorp/consul-k8s/pull/1869)] + ## 0.49.3 (January 30, 2023) IMPROVEMENTS: diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 3c296ff65e..efb8674631 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -2153,9 +2153,9 @@ connectInject: # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector # for more details. # - # By default, we exclude the kube-system namespace since usually users won't - # want those pods injected and also the local-path-storage namespace so that - # Kind (Kubernetes In Docker) can provision Pods used to create PVCs. + # By default, we exclude kube-system since usually users won't + # want those pods injected and local-path-storage and openebs so that + # Kind (Kubernetes In Docker) and OpenEBS (https://openebs.io/) respectively can provision Pods used to create PVCs. # Note that this exclusion is only supported in Kubernetes v1.21.1+. # # Example: @@ -2170,7 +2170,7 @@ connectInject: matchExpressions: - key: "kubernetes.io/metadata.name" operator: "NotIn" - values: ["kube-system","local-path-storage"] + values: ["kube-system","local-path-storage","openebs"] # List of k8s namespaces to allow Connect sidecar # injection in. If a k8s namespace is not included or is listed in `k8sDenyNamespaces`, From 9e5a3860982126cf09d1b5b3a5a66b31b018098e Mon Sep 17 00:00:00 2001 From: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com> Date: Fri, 3 Feb 2023 23:31:20 +0000 Subject: [PATCH 199/235] backport of commit ef500b3c31e5325e36bf956753842aa00d72a158 --- acceptance/framework/vault/helpers.go | 1 - 1 file changed, 1 deletion(-) diff --git a/acceptance/framework/vault/helpers.go b/acceptance/framework/vault/helpers.go index 6ebfb5cf62..4726e246ae 100644 --- a/acceptance/framework/vault/helpers.go +++ b/acceptance/framework/vault/helpers.go @@ -40,7 +40,6 @@ func ConfigurePKICerts(t *testing.T, "allow_bare_domains": "true", "allow_localhost": "true", "allow_subdomains": "true", - "generate_lease": "true", "max_ttl": maxTTL, } From 7a8adad67fae317e71b22045b934ba13f7844fe2 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Mon, 6 Feb 2023 22:57:06 -0500 Subject: [PATCH 200/235] Backport of Dockerfile: Remove gnupg from Consul k8s container into release/0.49.x (#1883) * manual fix of changelog Co-authored-by: David Yu --- CHANGELOG.md | 4 ++++ control-plane/Dockerfile | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 207bdcff3b..f6e029d6f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ BREAKING CHANGES: ``` [[GH-1869](https://github.com/hashicorp/consul-k8s/pull/1869)] +IMPROVEMENTS: +* Control Plane + * Remove extraneous `gnupg` depdency from `consul-k8s-control-plane` since it is no longer needed for validating binary artifacts prior to release. [[GH-1882](https://github.com/hashicorp/consul-k8s/pull/1882)] + ## 0.49.3 (January 30, 2023) IMPROVEMENTS: diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 921ac69784..f2b78fc8e0 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -84,7 +84,7 @@ LABEL name=${BIN_NAME} \ ENV BIN_NAME=${BIN_NAME} ENV VERSION=${PRODUCT_VERSION} -RUN apk add --no-cache ca-certificates curl gnupg libcap openssl su-exec iputils libc6-compat iptables +RUN apk add --no-cache ca-certificates libcap openssl su-exec iputils libc6-compat iptables # TARGETOS and TARGETARCH are set automatically when --platform is provided. ARG TARGETOS @@ -146,7 +146,7 @@ ARG TARGETARCH # Copy license for Red Hat certification. COPY LICENSE.md /licenses/mozilla.txt -RUN microdnf install -y ca-certificates gnupg libcap openssl shadow-utils iptables +RUN microdnf install -y ca-certificates libcap openssl shadow-utils iptables # Create a non-root user to run the software. On OpenShift, this # will not matter since the container is run as a random user and group From 3b7ff6b112836f554ef435cbe6e6f24d0834a1e3 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Tue, 7 Feb 2023 00:26:05 -0500 Subject: [PATCH 201/235] Backport of Dockerfile: remove `gnupg` from dev image into release/0.49.x (#1886) Co-authored-by: David Yu --- CHANGELOG.md | 2 +- control-plane/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e029d6f2..43a9491879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ BREAKING CHANGES: IMPROVEMENTS: * Control Plane - * Remove extraneous `gnupg` depdency from `consul-k8s-control-plane` since it is no longer needed for validating binary artifacts prior to release. [[GH-1882](https://github.com/hashicorp/consul-k8s/pull/1882)] + * Remove extraneous `gnupg` dependency from `consul-k8s-control-plane` since it is no longer needed for validating binary artifacts prior to release. [[GH-1882](https://github.com/hashicorp/consul-k8s/pull/1882)] ## 0.49.3 (January 30, 2023) diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index f2b78fc8e0..5a418b5bf4 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -37,7 +37,7 @@ LABEL name=${BIN_NAME} \ ENV BIN_NAME=${BIN_NAME} ENV VERSION=${VERSION} -RUN apk add --no-cache ca-certificates curl gnupg libcap openssl su-exec iputils libc6-compat iptables +RUN apk add --no-cache ca-certificates curl libcap openssl su-exec iputils libc6-compat iptables # Create a non-root user to run the software. RUN addgroup ${BIN_NAME} && \ From 032fbaf2b19f9b7d9139802b8aafc3f711c42747 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Tue, 7 Feb 2023 11:19:10 -0500 Subject: [PATCH 202/235] Pre-release update for 0.49.4 (#1888) --- CHANGELOG.md | 2 +- charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43a9491879..df9aab2660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## UNRELEASED +## 0.49.4 (February 7, 2023) BREAKING CHANGES: * Helm: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 6001345e96..0344240c9f 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.4-dev +version: 0.49.4 appVersion: 1.13.6 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: true + artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.6 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.4-dev + image: hashicorp/consul-k8s-control-plane:0.49.4 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index efb8674631..b0b6d24b2b 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.4-dev + imageK8S: hashicorp/consul-k8s-control-plane:0.49.4 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 71d63e9061..758af326de 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 71d63e9061..758af326de 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From bd3ccb0ef07f4150fdea3c1d5a630734b569d822 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Thu, 9 Feb 2023 11:17:02 -0500 Subject: [PATCH 203/235] Prepare dev 0.49.5 (#1896) --- CHANGELOG.md | 2 ++ charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df9aab2660..75beb62542 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## UNRELEASED + ## 0.49.4 (February 7, 2023) BREAKING CHANGES: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 0344240c9f..a6c19db870 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.4 +version: 0.49.5-dev appVersion: 1.13.6 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: false + artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.6 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.4 + image: hashicorp/consul-k8s-control-plane:0.49.5-dev - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index b0b6d24b2b..ed49bad0d6 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.4 + imageK8S: hashicorp/consul-k8s-control-plane:0.49.5-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 758af326de..f89582cd9d 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.4" + Version = "0.49.5" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 758af326de..f89582cd9d 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.4" + Version = "0.49.5" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 05b8b08828b87847305921fab9ca0ba1f9d2c61d Mon Sep 17 00:00:00 2001 From: Luke Kysow <1034429+lkysow@users.noreply.github.com> Date: Fri, 10 Feb 2023 20:29:09 +0000 Subject: [PATCH 204/235] backport of commit d16135140e706f94ec64f2c27fc46e78c63bfbc0 --- charts/consul/values.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index ed49bad0d6..61090a92fd 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -445,8 +445,9 @@ global: # # Note that we need the CA key so that we can generate server and client certificates. # It is particularly important for the client certificates since they need to have host IPs - # as Subject Alternative Names. In the future, we may support bringing your own server - # certificates. + # as Subject Alternative Names. If you are setting server certs yourself via `server.serverCert` + # and you are not enabling clients (or clients are enabled with autoEncrypt) then you do not + # need to provide the CA key. caKey: # The name of the Kubernetes or Vault secret that holds the CA key. # @type: string From d39bfd458081049b4c6291cf3d63afa211c31346 Mon Sep 17 00:00:00 2001 From: "R.B. Boyer" <4903+rboyer@users.noreply.github.com> Date: Wed, 15 Feb 2023 16:03:08 -0600 Subject: [PATCH 205/235] [0.49.x] remove livenessProbe from pods with preStop lifecycle hooks that delete ACL tokens (#1914) Currently we use an init container to create a consul ACL token via an auth method. We configure a preStop lifecycle hook to delete this token to avoid leaking it but this executes when containers get restarted, not just when the pod is destroyed. This means that if a container livenessProbe fails and triggers a container to be restarted in place the token it was using will be destroyed but not recreated. --- .github/workflows/test.yml | 18 +++++++++--------- .../templates/connect-inject-deployment.yaml | 9 --------- .../templates/sync-catalog-deployment.yaml | 10 ---------- 3 files changed, 9 insertions(+), 28 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2196868c94..1e5de4c98e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,7 +55,7 @@ jobs: golangci-lint-helm-gen: needs: - get-go-version - uses: hashicorp/consul-k8s/.github/workflows/reusable-golangci-lint.yml@main + uses: ./.github/workflows/reusable-golangci-lint.yml with: directory: hack/helm-reference-gen go-version: ${{ needs.get-go-version.outputs.go-version }} @@ -64,7 +64,7 @@ jobs: unit-helm-gen: needs: [get-go-version, golangci-lint-helm-gen, validate-helm-gen] - uses: hashicorp/consul-k8s/.github/workflows/reusable-unit.yml@main + uses: ./.github/workflows/reusable-unit.yml with: directory: hack/helm-reference-gen go-version: ${{ needs.get-go-version.outputs.go-version }} @@ -106,7 +106,7 @@ jobs: golangci-lint-control-plane: needs: - get-go-version - uses: hashicorp/consul-k8s/.github/workflows/reusable-golangci-lint.yml@main + uses: ./.github/workflows/reusable-golangci-lint.yml with: directory: control-plane go-version: ${{ needs.get-go-version.outputs.go-version }} @@ -245,14 +245,14 @@ jobs: golangci-lint-acceptance: needs: - get-go-version - uses: hashicorp/consul-k8s/.github/workflows/reusable-golangci-lint.yml@main + uses: ./.github/workflows/reusable-golangci-lint.yml with: directory: acceptance go-version: ${{ needs.get-go-version.outputs.go-version }} unit-acceptance-framework: needs: [get-go-version, golangci-lint-acceptance] - uses: hashicorp/consul-k8s/.github/workflows/reusable-unit.yml@main + uses: ./.github/workflows/reusable-unit.yml with: directory: acceptance/framework go-version: ${{ needs.get-go-version.outputs.go-version }} @@ -260,14 +260,14 @@ jobs: golangci-lint-cli: needs: - get-go-version - uses: hashicorp/consul-k8s/.github/workflows/reusable-golangci-lint.yml@main + uses: ./.github/workflows/reusable-golangci-lint.yml with: directory: cli go-version: ${{ needs.get-go-version.outputs.go-version }} unit-cli: needs: [get-go-version, golangci-lint-cli] - uses: hashicorp/consul-k8s/.github/workflows/reusable-unit.yml@main + uses: ./.github/workflows/reusable-unit.yml with: directory: cli go-version: ${{ needs.get-go-version.outputs.go-version }} @@ -302,7 +302,7 @@ jobs: # acceptance-tproxy: # needs: [get-go-version, unit-cli, dev-upload-docker, unit-acceptance-framework, unit-test-helm-templates] # needs: dev-upload-docker -# uses: hashicorp/consul-k8s/.github/workflows/reusable-acceptance.yml@main +# uses: ./.github/workflows/reusable-acceptance.yml # with: # name: acceptance-tproxy # directory: acceptance/tests @@ -315,7 +315,7 @@ jobs: # acceptance: # #needs: [get-go-version, unit-cli, dev-upload-docker, unit-acceptance-framework, unit-test-helm-templates] # needs: dev-upload-docker -# uses: hashicorp/consul-k8s/.github/workflows/reusable-acceptance.yml@main +# uses: ./.github/workflows/reusable-acceptance.yml # with: # name: acceptance # directory: acceptance/tests diff --git a/charts/consul/templates/connect-inject-deployment.yaml b/charts/consul/templates/connect-inject-deployment.yaml index 63fb5ae84c..6cb1b3f23a 100644 --- a/charts/consul/templates/connect-inject-deployment.yaml +++ b/charts/consul/templates/connect-inject-deployment.yaml @@ -293,15 +293,6 @@ spec: failureThreshold: 15 periodSeconds: 2 timeoutSeconds: 5 - livenessProbe: - httpGet: - path: /readyz/ready - port: 9445 - scheme: HTTP - failureThreshold: 2 - initialDelaySeconds: 1 - successThreshold: 1 - timeoutSeconds: 5 readinessProbe: httpGet: path: /readyz/ready diff --git a/charts/consul/templates/sync-catalog-deployment.yaml b/charts/consul/templates/sync-catalog-deployment.yaml index d64ca05f62..ef793e1190 100644 --- a/charts/consul/templates/sync-catalog-deployment.yaml +++ b/charts/consul/templates/sync-catalog-deployment.yaml @@ -214,16 +214,6 @@ spec: - | consul-k8s-control-plane consul-logout -consul-api-timeout={{ .Values.global.consulAPITimeout }} {{- end }} - livenessProbe: - httpGet: - path: /health/ready - port: 8080 - scheme: HTTP - failureThreshold: 3 - initialDelaySeconds: 30 - periodSeconds: 5 - successThreshold: 1 - timeoutSeconds: 5 readinessProbe: httpGet: path: /health/ready From 48bcc90fbb6fb94b1c20c3c1fb13d857b31fdc0f Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 22 Feb 2023 12:58:34 -0500 Subject: [PATCH 206/235] Backport of Dockerfile: bump Alpine base image to 3.17 into release/0.49.x (#1936) * Manual backport to 0.49.x Co-authored-by: David Yu --- CHANGELOG.md | 4 ++++ control-plane/Dockerfile | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75beb62542..9bd8714c8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## UNRELEASED +IMPROVEMENTS: +* Control Plane + * Update alpine to 3.17 in the Docker image. [[GH-1934](https://github.com/hashicorp/consul-k8s/pull/1934)] + ## 0.49.4 (February 7, 2023) BREAKING CHANGES: diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 5a418b5bf4..8d23426673 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -15,7 +15,7 @@ # ----------------------------------- # BIN_NAME is a requirement in the hashicorp docker github action -FROM alpine:3.16 AS dev +FROM alpine:3.17 AS dev # NAME and VERSION are the name of the software in releases.hashicorp.com # and the version to download. Example: NAME=consul VERSION=1.2.3. @@ -66,7 +66,7 @@ CMD /bin/${BIN_NAME} # We don't rebuild the software because we want the exact checksums and # binary signatures to match the software and our builds aren't fully # reproducible currently. -FROM alpine:3.16 AS release-default +FROM alpine:3.17 AS release-default ARG BIN_NAME=consul-k8s-control-plane ARG CNI_BIN_NAME=consul-cni From 25d1532c082a04ee475097662e99aad44e63cb14 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Fri, 24 Feb 2023 10:12:36 -0800 Subject: [PATCH 207/235] Enable envoy bootstrap config logging if global.logLevel == debug (#1910) --- .../ingress-gateways-deployment.yaml | 3 ++ .../templates/mesh-gateway-deployment.yaml | 3 ++ .../terminating-gateways-deployment.yaml | 3 ++ .../unit/ingress-gateways-deployment.bats | 30 +++++++++++++++++++ .../test/unit/mesh-gateway-deployment.bats | 29 ++++++++++++++++++ .../unit/terminating-gateways-deployment.bats | 30 +++++++++++++++++++ .../connect-inject/container_init.go | 11 +++++++ .../connect-inject/container_init_test.go | 19 ++++++++++++ 8 files changed, 128 insertions(+) diff --git a/charts/consul/templates/ingress-gateways-deployment.yaml b/charts/consul/templates/ingress-gateways-deployment.yaml index ed5724389e..1a2c1aa38f 100644 --- a/charts/consul/templates/ingress-gateways-deployment.yaml +++ b/charts/consul/templates/ingress-gateways-deployment.yaml @@ -388,6 +388,9 @@ spec: {{- if $root.Values.global.adminPartitions.enabled }} - -partition={{ $root.Values.global.adminPartitions.name }} {{- end }} + {{- if (eq $root.Values.global.logLevel "debug")}} + - -enable-config-gen-logging + {{- end }} livenessProbe: tcpSocket: port: 21000 diff --git a/charts/consul/templates/mesh-gateway-deployment.yaml b/charts/consul/templates/mesh-gateway-deployment.yaml index a74abce318..d9c876ba07 100644 --- a/charts/consul/templates/mesh-gateway-deployment.yaml +++ b/charts/consul/templates/mesh-gateway-deployment.yaml @@ -333,6 +333,9 @@ spec: {{- if .Values.global.adminPartitions.enabled }} - -partition={{ .Values.global.adminPartitions.name }} {{- end }} + {{- if eq .Values.global.logLevel "debug"}} + - -enable-config-gen-logging + {{- end }} livenessProbe: tcpSocket: port: {{ .Values.meshGateway.containerPort }} diff --git a/charts/consul/templates/terminating-gateways-deployment.yaml b/charts/consul/templates/terminating-gateways-deployment.yaml index 540fded2e6..405fd7de6a 100644 --- a/charts/consul/templates/terminating-gateways-deployment.yaml +++ b/charts/consul/templates/terminating-gateways-deployment.yaml @@ -343,6 +343,9 @@ spec: {{- if $root.Values.global.adminPartitions.enabled }} - -partition={{ $root.Values.global.adminPartitions.name }} {{- end }} + {{- if (eq $root.Values.global.logLevel "debug")}} + - -enable-config-gen-logging + {{- end }} livenessProbe: tcpSocket: port: 8443 diff --git a/charts/consul/test/unit/ingress-gateways-deployment.bats b/charts/consul/test/unit/ingress-gateways-deployment.bats index f4bbc40881..705bfc5963 100644 --- a/charts/consul/test/unit/ingress-gateways-deployment.bats +++ b/charts/consul/test/unit/ingress-gateways-deployment.bats @@ -1661,6 +1661,36 @@ EOF [[ "$output" =~ "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" ]] } +#-------------------------------------------------------------------- +# envoy bootstrap logging + +@test "ingressGateways/Deployment: envoy bootstrap logging is not present by default" { + cd `chart_dir` + local object=$(helm template \ + -s templates/ingress-gateways-deployment.yaml \ + --set 'ingressGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -s -r '.[0].spec.template.spec.containers[0]' | tee /dev/stderr) + + local actual=$(echo $object | yq -r '.command | any(contains("-enable-config-gen-logging"))' | tee /dev/stderr) + [ "${actual}" = "false" ] +} + +@test "ingressGateways/Deployment: envoy bootstrap logging flag is present if global.logLevel == debug" { + cd `chart_dir` + local object=$(helm template \ + -s templates/ingress-gateways-deployment.yaml \ + --set 'ingressGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.logLevel=debug' \ + . | tee /dev/stderr | + yq -s -r '.[0].spec.template.spec.containers[0]' | tee /dev/stderr) + + local actual=$(echo $object | yq -r '.command | any(contains("-enable-config-gen-logging"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # multiple gateways diff --git a/charts/consul/test/unit/mesh-gateway-deployment.bats b/charts/consul/test/unit/mesh-gateway-deployment.bats index 300886e713..5f3696ca7a 100755 --- a/charts/consul/test/unit/mesh-gateway-deployment.bats +++ b/charts/consul/test/unit/mesh-gateway-deployment.bats @@ -1788,6 +1788,35 @@ EOF [[ "$output" =~ "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" ]] } +#-------------------------------------------------------------------- +# envoy bootstrap logging + +@test "meshGateway/Deployment: envoy bootstrap logging is not present by default" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/mesh-gateway-deployment.yaml \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-enable-config-gen-logging"))' | tee /dev/stderr) + + [ "${actual}" = "false" ] +} + +@test "meshGateway/Deployment: envoy bootstrap logging flag is present if global.logLevel == debug" { + cd `chart_dir` + local actual=$(helm template \ + -s templates/mesh-gateway-deployment.yaml \ + --set 'meshGateway.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.logLevel=debug' \ + . | tee /dev/stderr | + yq '.spec.template.spec.containers[0].command | any(contains("-enable-config-gen-logging"))' | tee /dev/stderr) + + [ "${actual}" = "true" ] +} + + #-------------------------------------------------------------------- # get-auto-encrypt-client-ca diff --git a/charts/consul/test/unit/terminating-gateways-deployment.bats b/charts/consul/test/unit/terminating-gateways-deployment.bats index 5165c63565..19cee6f148 100644 --- a/charts/consul/test/unit/terminating-gateways-deployment.bats +++ b/charts/consul/test/unit/terminating-gateways-deployment.bats @@ -1475,6 +1475,36 @@ EOF [[ "$output" =~ "global.enableConsulNamespaces must be true if global.adminPartitions.enabled=true" ]] } +#-------------------------------------------------------------------- +# envoy bootstrap logging + +@test "terminatingGateways/Deployment: envoy bootstrap logging is not present by default" { + cd `chart_dir` + local object=$(helm template \ + -s templates/terminating-gateways-deployment.yaml \ + --set 'terminatingGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + . | tee /dev/stderr | + yq -s -r '.[0].spec.template.spec.containers[0]' | tee /dev/stderr) + + local actual=$(echo $object | yq -r '.command | any(contains("-enable-config-gen-logging"))' | tee /dev/stderr) + [ "${actual}" = "false" ] +} + +@test "terminatingGateways/Deployment: envoy bootstrap logging flag is present if global.logLevel == debug" { + cd `chart_dir` + local object=$(helm template \ + -s templates/terminating-gateways-deployment.yaml \ + --set 'terminatingGateways.enabled=true' \ + --set 'connectInject.enabled=true' \ + --set 'global.logLevel=debug' \ + . | tee /dev/stderr | + yq -s -r '.[0].spec.template.spec.containers[0]' | tee /dev/stderr) + + local actual=$(echo $object | yq -r '.command | any(contains("-enable-config-gen-logging"))' | tee /dev/stderr) + [ "${actual}" = "true" ] +} + #-------------------------------------------------------------------- # multiple gateways diff --git a/control-plane/connect-inject/container_init.go b/control-plane/connect-inject/container_init.go index 47dabbbe0b..a4bedc4e8c 100644 --- a/control-plane/connect-inject/container_init.go +++ b/control-plane/connect-inject/container_init.go @@ -9,6 +9,7 @@ import ( "text/template" "time" + "go.uber.org/zap/zapcore" corev1 "k8s.io/api/core/v1" "k8s.io/utils/pointer" ) @@ -71,6 +72,9 @@ type initContainerCommandData struct { // redirection is handled by the CNI plugin on pod creation. EnableCNI bool + // EnableEnvoyBootstrapLogging enables debug log output when generating the Envoy bootstrap config. + EnableEnvoyBootstrapLogging bool + // TProxyExcludeInboundPorts is a list of inbound ports to exclude from traffic redirection via // the consul connect redirect-traffic command. TProxyExcludeInboundPorts []string @@ -260,6 +264,10 @@ func (w *MeshWebhook) containerInit(namespace corev1.Namespace, pod corev1.Pod, } } + if w.LogLevel == zapcore.DebugLevel.String() { + data.EnableEnvoyBootstrapLogging = true + } + // Render the command var buf bytes.Buffer tpl := template.Must(template.New("root").Parse(strings.TrimSpace( @@ -479,6 +487,9 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD {{- if .ConsulNamespace }} -namespace="{{ .ConsulNamespace }}" \ {{- end }} + {{- if .EnableEnvoyBootstrapLogging }} + -enable-config-gen-logging \ + {{- end }} {{- if .MultiPort }} -admin-bind=127.0.0.1:{{ .EnvoyAdminPort }} \ {{- end }} diff --git a/control-plane/connect-inject/container_init_test.go b/control-plane/connect-inject/container_init_test.go index f4ab3eed47..96dc4ce7a4 100644 --- a/control-plane/connect-inject/container_init_test.go +++ b/control-plane/connect-inject/container_init_test.go @@ -8,6 +8,7 @@ import ( "time" "github.com/stretchr/testify/require" + "go.uber.org/zap/zapcore" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -160,6 +161,24 @@ consul-k8s-control-plane connect-init -pod-name=${POD_NAME} -pod-namespace=${POD -prometheus-ca-path="/certs/ca/" \ -prometheus-cert-file="/certs/server.crt" \ -prometheus-key-file="/certs/key.pem" \ + -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, + "", + "", + }, + { + "When logLevel is debug, enable logging for Envoy bootstrap config generation", + func(pod *corev1.Pod) *corev1.Pod { + pod.Annotations[annotationService] = "web" + return pod + }, + MeshWebhook{ + ConsulAPITimeout: 5 * time.Second, + LogLevel: zapcore.DebugLevel.String(), + }, + `# Generate the envoy bootstrap code +/consul/connect-inject/consul connect envoy \ + -proxy-id="$(cat /consul/connect-inject/proxyid)" \ + -enable-config-gen-logging \ -bootstrap > /consul/connect-inject/envoy-bootstrap.yaml`, "", "", From 4db3eb0780534298a18428f26986991932147639 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Mon, 27 Feb 2023 19:35:41 -0800 Subject: [PATCH 208/235] Backport of Update links to support DevDot into release/0.49.x (#1949) * fix merge conflicts --------- Co-authored-by: Tu Nguyen --- charts/consul/values.yaml | 222 ++++++++++++++++++++++++-------------- 1 file changed, 140 insertions(+), 82 deletions(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 61090a92fd..46a565a948 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -25,7 +25,7 @@ global: name: null # The domain Consul will answer DNS queries for - # (see `-domain` (https://www.consul.io/docs/agent/config/cli-flags#_domain)) and the domain services synced from + # (Refer to [`-domain`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_domain)) and the domain services synced from # Consul into Kubernetes will have, e.g. `service-name.service.consul`. domain: consul @@ -113,7 +113,7 @@ global: # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. - # See https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry for reference. + # Refer to https://kubernetes.io/docs/concepts/containers/images/#using-a-private-registry. # # Example: # @@ -138,13 +138,14 @@ global: datacenter: dc1 # Controls whether pod security policies are created for the Consul components - # created by this chart. See https://kubernetes.io/docs/concepts/policy/pod-security-policy/. + # created by this chart. Refer to https://kubernetes.io/docs/concepts/policy/pod-security-policy/. enablePodSecurityPolicies: false # secretsBackend is used to configure Vault as the secrets backend for the Consul on Kubernetes installation. # The Vault cluster needs to have the Kubernetes Auth Method, KV2 and PKI secrets engines enabled # and have necessary secrets, policies and roles created prior to installing Consul. - # See https://www.consul.io/docs/k8s/installation/vault for full instructions. + # Refer to [Vault as the Secrets Backend](https://developer.hashicorp.com/consul/docs/k8s/deployment-configurations/vault) + # documentation for full instructions. # # The Vault cluster _must_ not have the Consul cluster installed by this Helm chart as its storage backend # as that would cause a circular dependency. @@ -261,8 +262,8 @@ global: # The provider will be configured to use the Vault Kubernetes auth method # and therefore requires the role provided by `global.secretsBackend.vault.consulServerRole` # to have permissions to the root and intermediate PKI paths. - # Please see https://www.consul.io/docs/connect/ca/vault#vault-acl-policies - # for information on how to configure the Vault policies. + # Please refer to [Vault ACL policies](https://developer.hashicorp.com/consul/docs/connect/ca/vault#vault-acl-policies) + # documentation for information on how to configure the Vault policies. connectCA: # The address of the Vault server. address: "" @@ -271,15 +272,15 @@ global: authMethodPath: "kubernetes" # The path to a PKI secrets engine for the root certificate. - # For more details, please refer to [Vault Connect CA configuration](https://www.consul.io/docs/connect/ca/vault#rootpkipath). + # For more details, please refer to [Vault Connect CA configuration](https://developer.hashicorp.com/consul/docs/connect/ca/vault#rootpkipath). rootPKIPath: "" # The path to a PKI secrets engine for the generated intermediate certificate. - # For more details, please refer to [Vault Connect CA configuration](https://www.consul.io/docs/connect/ca/vault#intermediatepkipath). + # For more details, please refer to [Vault Connect CA configuration](https://developer.hashicorp.com/consul/docs/connect/ca/vault#intermediatepkipath). intermediatePKIPath: "" # Additional Connect CA configuration in JSON format. - # Please refer to [Vault Connect CA configuration](https://www.consul.io/docs/connect/ca/vault#configuration) + # Please refer to [Vault Connect CA configuration](https://developer.hashicorp.com/consul/docs/connect/ca/vault#configuration) # for all configuration options available for that provider. # # Example: @@ -337,7 +338,7 @@ global: secretName: null # Configures Consul's gossip encryption key. - # (see `-encrypt` (https://www.consul.io/docs/agent/config/cli-flags#_encrypt)). + # (Refer to [`-encrypt`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_encrypt)). # By default, gossip encryption is not enabled. The gossip encryption key may be set automatically or manually. # The recommended method is to automatically generate the key. # To automatically generate and set a gossip encryption key, set autoGenerate to true. @@ -345,7 +346,7 @@ global: # To manually generate a gossip encryption key, set secretName and secretKey and use Consul to generate # a key, saving this as a Kubernetes secret or Vault secret path and key. # If `global.secretsBackend.vault.enabled=true`, be sure to add the "data" component of the secretName path as required by - # the Vault KV-2 secrets engine [see example]. + # the Vault KV-2 secrets engine [refer to example]. # # ```shell-session # $ kubectl create secret generic consul-gossip-encryption-key --from-literal=key=$(consul keygen) @@ -370,12 +371,12 @@ global: # A list of addresses of upstream DNS servers that are used to recursively resolve DNS queries. # These values are given as `-recursor` flags to Consul servers and clients. - # See https://www.consul.io/docs/agent/config/cli-flags#_recursor for more details. + # Refer to [`-recursor`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_recursor) for more details. # If this is an empty array (the default), then Consul DNS will only resolve queries for the Consul top level domain (by default `.consul`). # @type: array recursors: [] - # Enables TLS (https://learn.hashicorp.com/tutorials/consul/tls-encryption-secure) + # Enables [TLS](https://developer.hashicorp.com/consul/tutorials/security/tls-encryption-secure) # across the cluster to verify authenticity of the Consul servers and clients. # Requires Consul v1.4.1+. tls: @@ -404,7 +405,7 @@ global: # If true, `verify_outgoing`, `verify_server_hostname`, # and `verify_incoming` for internal RPC communication will be set to `true` for Consul servers and clients. # Set this to false to incrementally roll out TLS on an existing Consul cluster. - # Please see https://consul.io/docs/k8s/operations/tls-on-existing-cluster + # Please refer to [TLS on existing clusters](https://developer.hashicorp.com/consul/docs/k8s/operations/tls-on-existing-cluster) # for more details. verify: true @@ -518,10 +519,10 @@ global: # tolerations configures the taints and tolerations for the server-acl-init # and server-acl-init-cleanup jobs. This should be a multi-line string matching the - # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + # [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. tolerations: "" - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) # labels for the server-acl-init and server-acl-init-cleanup jobs pod assignment, formatted as a multi-line string. # # Example: @@ -583,7 +584,7 @@ global: # This address must be reachable from the Consul servers in the primary datacenter. # This auth method will be used to provision ACL tokens for Consul components and is different # from the one used by the Consul Service Mesh. - # Please see the [Kubernetes Auth Method documentation](https://consul.io/docs/acl/auth-methods/kubernetes). + # Please refer to the [Kubernetes Auth Method documentation](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/kubernetes). # # You can retrieve this value from your `kubeconfig` by running: # @@ -691,7 +692,7 @@ server: image: null # The number of server agents to run. This determines the fault tolerance of - # the cluster. Please see the deployment table (https://consul.io/docs/internals/consensus#deployment-table) + # the cluster. Please refer to the [deployment table](https://developer.hashicorp.com/consul/docs/architecture/consensus#deployment-table) # for more information. replicas: 3 @@ -732,9 +733,9 @@ server: # # Vault Secrets backend: # If you are using Vault as a secrets backend, a Vault Policy must be created which allows `["create", "update"]` - # capabilities on the PKI issuing endpoint, which is usually of the form `pki/issue/consul-server`. - # Please see the following guide for steps to generate a compatible certificate: - # https://learn.hashicorp.com/tutorials/consul/vault-pki-consul-secure-tls + # capabilities on the PKI issuing endpoint, which is usually of the form `pki/issue/consul-server`. + # Complete [this tutorial](https://developer.hashicorp.com/consul/tutorials/vault-secure/vault-pki-consul-secure-tls) + # to learn how to generate a compatible certificate. # Note: when using TLS, both the `server.serverCert` and `global.tls.caCert` which points to the CA endpoint of this PKI engine # must be provided. serverCert: @@ -777,17 +778,17 @@ server: # storage classes, the PersistentVolumeClaims would need to be manually created. # A `null` value will use the Kubernetes cluster's default StorageClass. If a default # StorageClass does not exist, you will need to create one. - # Refer to the [Read/Write Tuning](https://developer.hashicorp.com/consul/docs/install/performance#read-write-tuning) - # section of the Server Performance Requirements documentation for considerations + # Refer to the [Read/Write Tuning](https://developer.hashicorp.com/consul/docs/install/performance#read-write-tuning) + # section of the Server Performance Requirements documentation for considerations # around choosing a performant storage class. # - # ~> **Note:** The [Reference Architecture](https://learn.hashicorp.com/tutorials/consul/reference-architecture#hardware-sizing-for-consul-servers) + # ~> **Note:** The [Reference Architecture](https://developer.hashicorp.com/consul/tutorials/production-deploy/reference-architecture#hardware-sizing-for-consul-servers) # contains best practices and recommendations for selecting suitable # hardware sizes for your Consul servers. # @type: string storageClass: null - # This will enable/disable Connect (https://consul.io/docs/connect). Setting this to true + # This will enable/disable [Connect](https://developer.hashicorp.com/consul/docs/connect). Setting this to true # _will not_ automatically secure pod communication, this # setting will only enable usage of the feature. Consul will automatically initialize # a new CA and set of certificates. Additional Connect settings can be configured @@ -809,7 +810,7 @@ server: # The resource requests (CPU, memory, etc.) # for each of the server agents. This should be a YAML map corresponding to a Kubernetes - # ResourceRequirements (https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#resourcerequirements-v1-core) + # [`ResourceRequirements``](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#resourcerequirements-v1-core) # object. NOTE: The use of a YAML string is deprecated. # # Example: @@ -862,12 +863,13 @@ server: # This value is used to carefully # control a rolling update of Consul server agents. This value specifies the - # partition (https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions) - # for performing a rolling update. Please read the linked Kubernetes documentation - # and https://www.consul.io/docs/k8s/upgrade#upgrading-consul-servers for more information. + # [partition](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#partitions) + # for performing a rolling update. Please read the linked Kubernetes + # and [Upgrade Consul](https://developer.hashicorp.com/consul/docs/k8s/upgrade#upgrading-consul-servers) + # documentation for more information. updatePartition: 0 - # This configures the PodDisruptionBudget (https://kubernetes.io/docs/tasks/run-application/configure-pdb/) + # This configures the [`PodDisruptionBudget`](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) # for the server cluster. disruptionBudget: # Enables registering a PodDisruptionBudget for the server @@ -883,7 +885,7 @@ server: # @type: integer maxUnavailable: null - # A raw string of extra JSON configuration (https://consul.io/docs/agent/options) for Consul + # A raw string of extra [JSON configuration](https://developer.hashicorp.com/consul/docs/agent/config/config-files) for Consul # servers. This will be saved as-is into a ConfigMap that is read by the Consul # server agents. This can be used to add additional configuration that # isn't directly exposed by the chart. @@ -946,7 +948,7 @@ server: # @type: array extraContainers: [] - # This value defines the affinity (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) + # This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) # for server pods. It defaults to allowing only a single server pod on each node, which # minimizes risk of the cluster becoming unusable if a node is lost. If you need # to run more pods per node (for example, testing on Minikube), set this value @@ -976,13 +978,15 @@ server: topologyKey: kubernetes.io/hostname # Toleration settings for server pods. This - # should be a multi-line string matching the Tolerations - # (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + # should be a multi-line string matching the + # [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) + # array in a Pod spec. tolerations: "" # Pod topology spread constraints for server pods. - # This should be a multi-line YAML string matching the `topologySpreadConstraints` array - # (https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) in a Pod Spec. + # This should be a multi-line YAML string matching the + # [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) + # array in a Pod Spec. # # This requires K8S >= 1.18 (beta) or 1.19 (stable). # @@ -1001,7 +1005,7 @@ server: # ``` topologySpreadConstraints: "" - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) # labels for server pod assignment, formatted as a multi-line string. # # Example: @@ -1015,7 +1019,7 @@ server: nodeSelector: null # This value references an existing - # Kubernetes `priorityClassName` (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) + # Kubernetes [`priorityClassName`](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) # that can be assigned to server pods. priorityClassName: "" @@ -1142,7 +1146,7 @@ externalServers: # If you are setting `global.acls.manageSystemACLs` and # `connectInject.enabled` to true, set `k8sAuthMethodHost` to the address of the Kubernetes API server. # This address must be reachable from the Consul servers. - # Please see the Kubernetes Auth Method documentation (https://consul.io/docs/acl/auth-methods/kubernetes). + # Please refer to the [Kubernetes Auth Method documentation](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/kubernetes). # # You could retrieve this value from your `kubeconfig` by running: # @@ -1168,7 +1172,7 @@ client: # @type: string image: null - # A list of valid `-retry-join` values (https://www.consul.io/docs/agent/config/cli-flags#_retry_join). + # A list of valid [`-retry-join` values](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_retry_join). # If this is `null` (default), then the clients will attempt to automatically # join the server cluster running within Kubernetes. # This means that with `server.enabled` set to true, clients will automatically @@ -1194,7 +1198,7 @@ client: grpc: true # nodeMeta specifies an arbitrary metadata key/value pair to associate with the node - # (see https://www.consul.io/docs/agent/config/cli-flags#_node_meta) + # (refer to [`-node-meta`](https://developer.hashicorp.com/consul/docs/agent/config/cli-flags#_node_meta)) nodeMeta: pod-name: ${HOSTNAME} host-ip: ${HOST_IP} @@ -1265,7 +1269,7 @@ client: # @recurse: false tlsInit: null - # A raw string of extra JSON configuration (https://consul.io/docs/agent/options) for Consul + # A raw string of extra [JSON configuration](https://developer.hashicorp.com/consul/docs/agent/config/config-files) for Consul # clients. This will be saved as-is into a ConfigMap that is read by the Consul # client agents. This can be used to add additional configuration that # isn't directly exposed by the chart. @@ -1370,7 +1374,7 @@ client: affinity: null # This value references an existing - # Kubernetes `priorityClassName` (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) + # Kubernetes [`priorityClassName`](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) # that can be assigned to client pods. priorityClassName: "" @@ -1406,7 +1410,7 @@ client: # @type: map extraEnvironmentVars: {} - # This value defines the Pod DNS policy (https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy) + # This value defines the [Pod DNS policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy) # for client pods to use. # @type: string dnsPolicy: null @@ -1419,7 +1423,8 @@ client: hostNetwork: false # updateStrategy for the DaemonSet. - # See https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#daemonset-update-strategy. + # Refer to the Kubernetes [Daemonset upgrade strategy](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#daemonset-update-strategy) + # documentation. # This should be a multi-line string mapping directly to the updateStrategy # # Example: @@ -1614,7 +1619,7 @@ ui: # Optionally set the ingressClassName. ingressClassName: "" - # pathType override - see: https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types + # pathType override - refer to: https://kubernetes.io/docs/concepts/services-networking/ingress/#path-types pathType: Prefix # hosts is a list of host name to create Ingress rules. @@ -1660,8 +1665,8 @@ ui: # @type: boolean # @default: global.metrics.enabled enabled: "-" - # Provider for metrics. See - # https://www.consul.io/docs/agent/options#ui_config_metrics_provider + # Provider for metrics. Refer to + # [`metrics_provider`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#ui_config_metrics_provider) # This value is only used if `ui.enabled` is set to true. # @type: string provider: "prometheus" @@ -1671,9 +1676,10 @@ ui: # @type: string baseURL: http://prometheus-server - # Corresponds to https://www.consul.io/docs/agent/options#ui_config_dashboard_url_templates configuration. + # Corresponds to [`dashboard_url_templates`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#ui_config_dashboard_url_templates) + # configuration. dashboardURLTemplates: - # Sets https://www.consul.io/docs/agent/options#ui_config_dashboard_url_templates_service. + # Sets [`dashboardURLTemplates.service`](https://developer.hashicorp.com/consul/docs/agent/config/config-files#ui_config_dashboard_url_templates_service). service: "" # Configure the catalog sync process to sync K8S with Consul @@ -1695,8 +1701,8 @@ syncCatalog: image: null # If true, all valid services in K8S are - # synced by default. If false, the service must be annotated - # (https://consul.io/docs/k8s/service-sync#sync-enable-disable) properly to sync. + # synced by default. If false, the service must be [annotated](https://developer.hashicorp.com/consul/docs/k8s/service-sync#enable-and-disable-sync) + # properly to sync. # In either case an annotation can override the default. default: true @@ -1835,7 +1841,7 @@ syncCatalog: # @type: string secretKey: null - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) # labels for catalog sync pod assignment, formatted as a multi-line string. # # Example: @@ -1931,7 +1937,7 @@ connectInject: # If true, the injector will inject the # Connect sidecar into all pods by default. Otherwise, pods must specify the - # injection annotation (https://consul.io/docs/k8s/connect#consul-hashicorp-com-connect-inject) + # [injection annotation](https://developer.hashicorp.com/consul/docs/k8s/connect#consul-hashicorp-com-connect-inject) # to opt-in to Connect injection. If this is true, pods can use the same annotation # to explicitly opt-out of injection. default: false @@ -1952,7 +1958,7 @@ connectInject: # Note: This value has no effect if transparent proxy is disabled on the pod. defaultOverwriteProbes: true - # This configures the PodDisruptionBudget (https://kubernetes.io/docs/tasks/run-application/configure-pdb/) + # This configures the [`PodDisruptionBudget`](https://kubernetes.io/docs/tasks/run-application/configure-pdb/) # for the service mesh sidecar injector. disruptionBudget: # This will enable/disable registering a PodDisruptionBudget for the @@ -2033,7 +2039,8 @@ connectInject: runAsUser: 0 # updateStrategy for the CNI installer DaemonSet. - # See https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#daemonset-update-strategy. + # Refer to the Kubernetes [Daemonset upgrade strategy](https://kubernetes.io/docs/tasks/manage-daemon/update-daemon-set/#daemonset-update-strategy) + # documentation. # This should be a multi-line string mapping directly to the updateStrategy # # Example: @@ -2151,12 +2158,12 @@ connectInject: # Selector for restricting the webhook to only specific namespaces. # Use with `connectInject.default: true` to automatically inject all pods in namespaces that match the selector. This should be set to a multiline string. - # See https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector + # Refer to https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector # for more details. # # By default, we exclude kube-system since usually users won't # want those pods injected and local-path-storage and openebs so that - # Kind (Kubernetes In Docker) and OpenEBS (https://openebs.io/) respectively can provision Pods used to create PVCs. + # Kind (Kubernetes In Docker) and [OpenEBS](https://openebs.io/) respectively can provision Pods used to create PVCs. # Note that this exclusion is only supported in Kubernetes v1.21.1+. # # Example: @@ -2257,8 +2264,8 @@ connectInject: # If set to an empty string all service accounts can log in. # This only has effect if ACLs are enabled. # - # See https://www.consul.io/docs/acl/acl-auth-methods.html#binding-rules - # and https://www.consul.io/docs/acl/auth-methods/kubernetes.html#trusted-identity-attributes + # Refer to Auth methods [Binding rules](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods#binding-rules) + # and [Trusted identiy attributes](https://developer.hashicorp.com/consul/docs/security/acl/auth-methods/kubernetes#trusted-identity-attributes) # for more details. # Requires Consul >= v1.5. aclBindingRuleSelector: "serviceaccount.name!=default" @@ -2288,7 +2295,7 @@ connectInject: # leads to unnecessary thread and memory usage and leaves unnecessary idle connections open. It is # advised to keep this number low for sidecars and high for edge proxies. # This will control the `--concurrency` flag to Envoy. - # For additional information see also: https://blog.envoyproxy.io/envoy-threading-model-a8d44b922310 + # For additional information, refer to https://blog.envoyproxy.io/envoy-threading-model-a8d44b922310 # # This setting can be overridden on a per-pod basis via this annotation: # - `consul.hashicorp.com/consul-envoy-proxy-concurrency` @@ -2450,7 +2457,7 @@ meshGateway: # Port that gets registered for WAN traffic. # If source is set to "Service" then this setting will have no effect. - # See the documentation for source as to which port will be used in that + # Refer to the documentation for source as to which port will be used in that # case. port: 443 @@ -2568,9 +2575,25 @@ meshGateway: memory: "50Mi" cpu: "50m" - # By default, we set an anti-affinity so that two gateway pods won't be - # on the same node. NOTE: Gateways require that Consul client agents are - # also running on the nodes alongside each gateway pod. + # This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) + # for mesh gateway pods. It defaults to `null` thereby allowing multiple gateway pods on each node. But if one would prefer + # a mode which minimizes risk of the cluster becoming unusable if a node is lost, set this value + # to the value in the example below. + # + # Example: + # + # ```yaml + # affinity: | + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchLabels: + # app: {{ template "consul.name" . }} + # release: "{{ .Release.Name }}" + # component: mesh-gateway + # topologyKey: kubernetes.io/hostname + # ``` + # @type: string affinity: | podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -2586,8 +2609,9 @@ meshGateway: tolerations: null # Pod topology spread constraints for mesh gateway pods. - # This should be a multi-line YAML string matching the `topologySpreadConstraints` array - # (https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) in a Pod Spec. + # This should be a multi-line YAML string matching the + # [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) + # array in a Pod Spec. # # This requires K8S >= 1.18 (beta) or 1.19 (stable). # @@ -2719,9 +2743,25 @@ ingressGateways: memory: "150Mi" cpu: "50m" - # By default, we set an anti-affinity so that two of the same gateway pods - # won't be on the same node. NOTE: Gateways require that Consul client agents are - # also running on the nodes alongside each gateway pod. + # This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) + # for ingress gateway pods. It defaults to `null` thereby allowing multiple gateway pods on each node. But if one would prefer + # a mode which minimizes risk of the cluster becoming unusable if a node is lost, set this value + # to the value in the example below. + # + # Example: + # + # ```yaml + # affinity: | + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchLabels: + # app: {{ template "consul.name" . }} + # release: "{{ .Release.Name }}" + # component: ingress-gateway + # topologyKey: kubernetes.io/hostname + # ``` + # @type: string affinity: | podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -2737,8 +2777,9 @@ ingressGateways: tolerations: null # Pod topology spread constraints for ingress gateway pods. - # This should be a multi-line YAML string matching the `topologySpreadConstraints` array - # (https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) in a Pod Spec. + # This should be a multi-line YAML string matching the + # [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) + # array in a Pod Spec. # # This requires K8S >= 1.18 (beta) or 1.19 (stable). # @@ -2853,9 +2894,25 @@ terminatingGateways: memory: "150Mi" cpu: "50m" - # By default, we set an anti-affinity so that two of the same gateway pods - # won't be on the same node. NOTE: Gateways require that Consul client agents are - # also running on the nodes alongside each gateway pod. + # This value defines the [affinity](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity) + # for terminating gateway pods. It defaults to `null` thereby allowing multiple gateway pods on each node. But if one would prefer + # a mode which minimizes risk of the cluster becoming unusable if a node is lost, set this value + # to the value in the example below. + # + # Example: + # + # ```yaml + # affinity: | + # podAntiAffinity: + # requiredDuringSchedulingIgnoredDuringExecution: + # - labelSelector: + # matchLabels: + # app: {{ template "consul.name" . }} + # release: "{{ .Release.Name }}" + # component: terminating-gateway + # topologyKey: kubernetes.io/hostname + # ``` + # @type: string affinity: | podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: @@ -2871,8 +2928,9 @@ terminatingGateways: tolerations: null # Pod topology spread constraints for terminating gateway pods. - # This should be a multi-line YAML string matching the `topologySpreadConstraints` array - # (https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) in a Pod Spec. + # This should be a multi-line YAML string matching the + # [`topologySpreadConstraints`](https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/) + # array in a Pod Spec. # # This requires K8S >= 1.18 (beta) or 1.19 (stable). # @@ -2957,7 +3015,7 @@ apiGateway: # When true a GatewayClass is configured to automatically work with Consul as installed by helm. enabled: true - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) # labels for gateway pod assignment, formatted as a multi-line string. # # Example: @@ -3042,11 +3100,11 @@ apiGateway: annotations: null # This value references an existing - # Kubernetes `priorityClassName` (https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) + # Kubernetes [`priorityClassName`](https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#pod-priority) # that can be assigned to api-gateway-controller pods. priorityClassName: "" - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) # labels for api-gateway-controller pod assignment, formatted as a multi-line string. # # Example: @@ -3060,7 +3118,7 @@ apiGateway: nodeSelector: null # This value defines the tolerations for api-gateway-controller pod, this should be a multi-line string matching the - # Tolerations (https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. + # [Tolerations](https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/) array in a Pod spec. # # @type: string tolerations: null @@ -3110,7 +3168,7 @@ webhookCertManager: # @type: string tolerations: null - # This value defines `nodeSelector` (https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) + # This value defines [`nodeSelector`](https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector) # labels for the webhook-cert-manager pod assignment, formatted as a multi-line string. # # Example: From be66d78da6c2a8dea8bc4fca78cee3b5af9ffc08 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:15:35 -0800 Subject: [PATCH 209/235] Cherry pick terraform checks (#1962) * added CI test to catch bad terraform formatting * formatted terraform files --- .github/workflows/test.yml | 14 ++++++++++++++ Makefile | 10 ++++++++++ charts/consul/test/terraform/aks/variables.tf | 2 +- charts/consul/test/terraform/eks/variables.tf | 2 +- charts/consul/test/terraform/gke/variables.tf | 2 +- .../consul/test/terraform/openshift/variables.tf | 2 +- .../build-support/scripts/terraformfmtcheck.sh | 14 ++++++++++++++ 7 files changed, 42 insertions(+), 4 deletions(-) create mode 100755 control-plane/build-support/scripts/terraformfmtcheck.sh diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1e5de4c98e..422e0654f5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,20 @@ env: GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. jobs: + terraform-fmt-check: + name: "Terraform format check" + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Setup Terraform + uses: hashicorp/setup-terraform@v2 + with: + terraform_version: TERRAFORM_VERSION + terraform_wrapper: false + - name: Run Terraform checks + run: | + make terraform-fmt-check TERRAFORM_DIR="${{ github.workspace }}" + get-go-version: name: "Determine Go toolchain version" runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 43a8e16b0d..6ad59a2a91 100644 --- a/Makefile +++ b/Makefile @@ -75,6 +75,16 @@ kind-cni: kind create cluster --config=$(CURDIR)/acceptance/framework/environment/cni-kind/kind.config --name dc2 --image kindest/node:v1.23.6 make kind-cni-calico +# Perform a terraform fmt check but don't change anything +terraform-fmt-check: + @$(CURDIR)/control-plane/build-support/scripts/terraformfmtcheck.sh $(TERRAFORM_DIR) +.PHONY: terraform-fmt-check + +# Format all terraform files according to terraform fmt +terraform-fmt: + @terraform fmt -recursive +.PHONY: terraform-fmt + # ===========> CLI Targets diff --git a/charts/consul/test/terraform/aks/variables.tf b/charts/consul/test/terraform/aks/variables.tf index 1651ce7b09..bb9dbef537 100644 --- a/charts/consul/test/terraform/aks/variables.tf +++ b/charts/consul/test/terraform/aks/variables.tf @@ -27,7 +27,7 @@ variable "cluster_count" { } variable "tags" { - type = map + type = map(any) default = {} description = "Tags to attach to the created resources." } diff --git a/charts/consul/test/terraform/eks/variables.tf b/charts/consul/test/terraform/eks/variables.tf index 361a5f5c45..05f383168b 100644 --- a/charts/consul/test/terraform/eks/variables.tf +++ b/charts/consul/test/terraform/eks/variables.tf @@ -21,7 +21,7 @@ variable "role_arn" { } variable "tags" { - type = map + type = map(any) default = {} description = "Tags to attach to the created resources." } diff --git a/charts/consul/test/terraform/gke/variables.tf b/charts/consul/test/terraform/gke/variables.tf index 04d214cedb..ef4a429116 100644 --- a/charts/consul/test/terraform/gke/variables.tf +++ b/charts/consul/test/terraform/gke/variables.tf @@ -30,7 +30,7 @@ variable "cluster_count" { } variable "labels" { - type = map + type = map(any) default = {} description = "Labels to attach to the created resources." } diff --git a/charts/consul/test/terraform/openshift/variables.tf b/charts/consul/test/terraform/openshift/variables.tf index f2479e3229..1df518f8ed 100644 --- a/charts/consul/test/terraform/openshift/variables.tf +++ b/charts/consul/test/terraform/openshift/variables.tf @@ -9,7 +9,7 @@ variable "cluster_count" { } variable "tags" { - type = map + type = map(any) default = {} description = "Tags to attach to the created resources." } diff --git a/control-plane/build-support/scripts/terraformfmtcheck.sh b/control-plane/build-support/scripts/terraformfmtcheck.sh new file mode 100755 index 0000000000..0f962a1c1b --- /dev/null +++ b/control-plane/build-support/scripts/terraformfmtcheck.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +# Check terraform fmt +echo "==> Checking that code complies with terraform fmt requirements..." +tffmt_files=$(terraform fmt -check -recursive "$1") +if [[ -n ${tffmt_files} ]]; then + echo 'terraform fmt needs to be run on the following files:' + echo "${tffmt_files}" + echo "You can use the command: \`make terraform-fmt\` to reformat all terraform code." + exit 1 +fi + +echo "==> Check code compile completed successfully" +exit 0 \ No newline at end of file From 6143feb2a6269e48215f75d6217b30d958f82bbc Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Tue, 28 Feb 2023 14:21:02 -0800 Subject: [PATCH 210/235] update prepare release to update the changelog (#1959) - Prepare release now requires an additional LAST_RELEASE_GIT_TAG environment variable required by go-changelog - removed adding the unreleased tag to the Changelog as we will no longer be doing that. All changelog entries will be added at the time of release by the go-changelog tool --- .changelog/changelog.tmpl | 57 ++++++ .changelog/note.tmpl | 3 + .github/workflows/changelog-checker.yml | 46 +++++ CONTRIBUTING.md | 41 ++++ Makefile | 4 +- .../build-support/functions/10-util.sh | 188 ++++++------------ 6 files changed, 206 insertions(+), 133 deletions(-) create mode 100644 .changelog/changelog.tmpl create mode 100644 .changelog/note.tmpl create mode 100644 .github/workflows/changelog-checker.yml diff --git a/.changelog/changelog.tmpl b/.changelog/changelog.tmpl new file mode 100644 index 0000000000..c1de4293b9 --- /dev/null +++ b/.changelog/changelog.tmpl @@ -0,0 +1,57 @@ +{{- if index .NotesByType "breaking-change" -}} +BREAKING CHANGES: + +{{range index .NotesByType "breaking-change" -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.security }} +SECURITY: + +{{range .NotesByType.security -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.feature }} +FEATURES: + +{{range .NotesByType.feature -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- $improvements := combineTypes .NotesByType.improvement .NotesByType.enhancement -}} +{{- if $improvements }} +IMPROVEMENTS: + +{{range $improvements | sort -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.deprecation }} +DEPRECATIONS: + +{{range .NotesByType.deprecation -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.bug }} +BUG FIXES: + +{{range .NotesByType.bug -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + +{{- if .NotesByType.note }} +NOTES: + +{{range .NotesByType.note -}} +* {{ template "note" . }} +{{ end -}} +{{- end -}} + diff --git a/.changelog/note.tmpl b/.changelog/note.tmpl new file mode 100644 index 0000000000..7588c65fd4 --- /dev/null +++ b/.changelog/note.tmpl @@ -0,0 +1,3 @@ +{{- define "note" -}} +{{.Body}}{{if not (stringHasPrefix .Issue "_")}} [[GH-{{- .Issue -}}](https://github.com/hashicorp/consul-k8s/issues/{{- .Issue -}})]{{end}} +{{- end -}} diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml new file mode 100644 index 0000000000..bb13255d29 --- /dev/null +++ b/.github/workflows/changelog-checker.yml @@ -0,0 +1,46 @@ +# This workflow checks that there is either a 'pr/no-changelog' label applied to a PR +# or there is a .changelog/.txt file associated with a PR for a changelog entry + +name: Changelog Checker + +on: + pull_request: + types: [opened, synchronize, labeled] + # Runs on PRs to main and all release branches + branches: + - main + - release/* + +jobs: + # checks that a .changelog entry is present for a PR + changelog-check: + # If there a `pr/no-changelog` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` + if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-changelog') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 0 # by default the checkout action doesn't checkout all branches + - name: Check for changelog entry in diff + run: | + # check if there is a diff in the .changelog directory + # for PRs against the main branch, the changelog file name should match the PR number + if [ "${{ github.event.pull_request.base.ref }}" = "${{ github.event.repository.default_branch }}" ]; then + enforce_matching_pull_request_number="matching this PR number " + changelog_file_path=".changelog/(_)?${{ github.event.pull_request.number }}.txt" + else + changelog_file_path=".changelog/[_0-9]*.txt" + fi + + changelog_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/main")" | egrep ${changelog_file_path}) + + # If we do not find a file in .changelog/, we fail the check + if [ -z "$changelog_files" ]; then + # Fail status check when no .changelog entry was found on the PR + echo "Did not find a .changelog entry ${enforce_matching_pull_request_number}and the 'pr/no-changelog' label was not applied. Reference - https://github.com/hashicorp/consul/pull/8387" + exit 1 + else + echo "Found .changelog entry in PR!" + fi diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 14875e1d55..f180f5071d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,6 +23,7 @@ 1. [Writing Unit tests](#writing-unit-tests) 1. [Writing Acceptance tests](#writing-acceptance-tests) 1. [Helm Reference Docs](#helm-reference-docs) +1. [Adding a Changelog Entry](#adding-a-changelog-entry) ## Contributing 101 @@ -1015,3 +1016,43 @@ So that the documentation can look like: ```markdown - `ports` ((#v-ingressgateways-defaults-service-ports)) (`array: [{port: 8080, port: 8443}]`) - Port docs ``` + +## Adding a Changelog Entry + +Any change that a Consul-K8s user might need to know about should have a changelog entry. + +What doesn't need a changelog entry? +- Typos/fixes, unless they are in a public-facing API +- Code changes we are certain no Consul-K8s users will need to know about + +To include a [changelog entry](../.changelog) in a PR, commit a text file +named `.changelog/.txt`, where `` is the number associated with the open +PR in GitHub. The text file should describe the changes in the following format: + +```` +```release-note: +: +``` +```` + +Valid values for `` include: +- `feature`: for the addition of a new feature +- `improvement`: for an improvement (not a bug fix) to an existing feature +- `bug`: for a bug fix +- `security`: for any Common Vulnerabilities and Exposures (CVE) resolutions +- `breaking-change`: for any change that is not fully backwards-compatible +- `deprecation`: for functionality which is now marked for removal in a future release + +`` is meant to categorize the functionality affected by the change. +Some common values are: +- `cli`: related to the command-line interface and its commands +- `control-plane`: related to control-plane functionality +- `helm`: related to the charts module and any files, yaml, go, etc. therein + +There may be cases where a `code area` doesn't make sense (i.e. addressing a Go CVE). In these +cases it is okay not to provide a `code area`. + +For more examples, look in the [`.changelog/`](../.changelog) folder for existing changelog entries. + +If a PR deserves multiple changelog entries, just add multiple entries separated by a newline +in the format described above to the `.changelog/.txt` file. diff --git a/Makefile b/Makefile index 6ad59a2a91..daee6b693b 100644 --- a/Makefile +++ b/Makefile @@ -156,7 +156,7 @@ endif ifndef RELEASE_DATE $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) endif - source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_release $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(PRERELEASE_VERSION) + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_release $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(LAST_RELEASE_GIT_TAG) $(PRERELEASE_VERSION) prepare-dev: ifndef RELEASE_VERSION @@ -168,7 +168,7 @@ endif ifndef NEXT_RELEASE_VERSION $(error NEXT_RELEASE_VERSION is required) endif - source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_dev $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(NEXT_RELEASE_VERSION) $(PRERELEASE_VERSION) + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_dev $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(NEXT_RELEASE_VERSION) # ===========> Makefile config diff --git a/control-plane/build-support/functions/10-util.sh b/control-plane/build-support/functions/10-util.sh index 90cfd9660e..8367c22743 100644 --- a/control-plane/build-support/functions/10-util.sh +++ b/control-plane/build-support/functions/10-util.sh @@ -643,6 +643,7 @@ function update_version_helm { # $1 - Path to the directory where the root of the Helm chart is # $2 - Version string # $3 - PreRelease version (if unset will become an empty string) + # $4 - Image base path # # Returns: # 0 - success @@ -669,11 +670,10 @@ function update_version_helm { then full_version="$2-$3" fi - local image_k8s="hashicorp\/consul-k8s-control-plane:$full_version" - sed_i ${SED_EXT} -e "s/(imageK8S:[[:space:]]*hashicorp\/consul-k8s-control-plane:)[^\"]*/\1${full_version}/g" "${vfile}" + sed_i ${SED_EXT} -e "s/(imageK8S:.*\/consul-k8s-control-plane:)[^\"]*/imageK8S: $4${full_version}/g" "${vfile}" sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version}/g" "${cfile}" - sed_i ${SED_EXT} -e "s/(image:[[:space:]]*hashicorp\/consul-k8s-control-plane:)[^\"]*/\1${full_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(image:.*\/consul-k8s-control-plane:)[^\"]*/image: $4${full_version}/g" "${cfile}" if test -z "$3" then @@ -684,100 +684,13 @@ function update_version_helm { return $? } -function set_changelog_version { - # Arguments: - # $1 - Path to top level Consul source - # $2 - Version to put into the Changelog - # $3 - Release Date - # - # Returns: - # 0 - success - # * - error - - local changelog="${1}/CHANGELOG.md" - local version="$2" - local rel_date="$3" - - if ! test -f "${changelog}" - then - err "ERROR: File not found: ${changelog}" - return 1 - fi - - if test -z "${version}" - then - err "ERROR: Must specify a version to put into the changelog" - return 1 - fi - - if test -z "${rel_date}" - then - rel_date=$(date +"%B %d, %Y") - fi - - sed_i ${SED_EXT} -e "s/## UNRELEASED/## ${version} (${rel_date})/" "${changelog}" - return $? -} - -function unset_changelog_version { - # Arguments: - # $1 - Path to top level Consul source - # - # Returns: - # 0 - success - # * - error - - local changelog="${1}/CHANGELOG.md" - - if ! test -f "${changelog}" - then - err "ERROR: File not found: ${changelog}" - return 1 - fi - - sed_i ${SED_EXT} -e "1 s/^## [0-9]+\.[0-9]+\.[0-9]+ \([^)]*\)/## UNRELEASED/" "${changelog}" - return $? -} - -function add_unreleased_to_changelog { - # Arguments: - # $1 - Path to top level Consul source - # - # Returns: - # 0 - success - # * - error - - local changelog="${1}/CHANGELOG.md" - - if ! test -f "${changelog}" - then - err "ERROR: File not found: ${changelog}" - return 1 - fi - - # Check if we are already in unreleased mode - if head -n 1 "${changelog}" | grep -q -c UNRELEASED - then - return 0 - fi - - local tfile="$(mktemp) -t "CHANGELOG.md_")" - ( - echo -e "## UNRELEASED\n" > "${tfile}" && - cat "${changelog}" >> "${tfile}" && - cp "${tfile}" "${changelog}" - ) - local ret=$? - rm "${tfile}" - return $ret -} - function set_version { # Arguments: # $1 - Path to top level Consul source # $2 - The version of the release # $3 - The release date # $4 - The pre-release version + # $5 - The helm docker image base path # # # Returns: @@ -802,21 +715,18 @@ function set_version { status_stage "==> Updating control-plane version/version.go with version info: ${vers} "$4"" if ! update_version "${sdir}/control-plane/version/version.go" "${vers}" "$4" then - unset_changelog_version "${sdir}" return 1 fi status_stage "==> Updating cli version/version.go with version info: ${vers} "$4"" if ! update_version "${sdir}/cli/version/version.go" "${vers}" "$4" then - unset_changelog_version "${sdir}" return 1 fi status_stage "==> Updating Helm chart versions with version info: ${vers} "$4"" - if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" + if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" "$5" then - unset_changelog_version "${sdir}" return 1 fi @@ -824,31 +734,52 @@ function set_version { } function set_changelog { - # Arguments: - # $1 - Path to top level Consul source - # $2 - The version of the release - # $3 - The release date - # $4 - The pre-release version - # - # - # Returns: - # 0 - success - # * - error - local sdir="$1" - local vers="$2" - local rel_date="$(date +"%B %d, %Y")" - if test -n "$3" - then - rel_date="$3" - fi + # Arguments: + # $1 - Path to top level Consul source + # $2 - Version + # $3 - Release Date + # $4 - The last git release tag + # + # + # Returns: + # 0 - success + # * - error - local changelog_vers="${vers}" - if test -n "$4" - then - changelog_vers="${vers}-$4" - fi - status_stage "==> Updating CHANGELOG.md with release info: ${changelog_vers} (${rel_date})" - set_changelog_version "${sdir}" "${changelog_vers}" "${rel_date}" || return 1 + # Check if changelog-build is installed + if ! command -v changelog-build &> /dev/null; then + echo "Error: changelog-build is not installed. Please install it and try again." + exit 1 + fi + + local curdir="$1" + local version="$2" + local rel_date="$(date +"%B %d, %Y")" + if test -n "$3" + then + rel_date="$3" + fi + local last_release_date_git_tag=$4 + + if test -z "${version}" + then + err "ERROR: Must specify a version to put into the changelog" + return 1 + fi + + if [ -z "$LAST_RELEASE_GIT_TAG" ]; then + echo "Error: LAST_RELEASE_GIT_TAG not specified." + exit 1 + fi + +cat < tmp && mv tmp "${curdir}"/CHANGELOG.MD +## ${version} (${rel_date}) +$(changelog-build -last-release ${LAST_RELEASE_GIT_TAG} \ + -entries-dir .changelog/ \ + -changelog-template .changelog/changelog.tmpl \ + -note-template .changelog/note.tmpl \ + -this-release $(git rev-parse HEAD)) + +EOT } function prepare_release { @@ -856,14 +787,16 @@ function prepare_release { # $1 - Path to top level Consul source # $2 - The version of the release # $3 - The release date - # $4 - The pre-release version + # $4 - The last release git tag for this branch (eg. v1.1.0) + # $5 - The pre-release version # # # Returns: # 0 - success # * - error - echo "release version: " $1 $2 $3 $4 - set_version "$1" "$2" "$3" "$4" + + echo "release version: " "$1" "$2" "$3" "$4" + set_version "$1" "$2" "$3" "$5" "hashicorp\/consul-k8s-control-plane:" set_changelog "$1" "$2" "$3" "$4" } @@ -873,21 +806,14 @@ function prepare_dev { # $2 - The version of the release # $3 - The release date # $4 - The version of the next release - # $5 - The pre-release version (for setting beta in changelog) + # $5 - The last release git tag for this branch (eg. v1.1.0) # # Returns: # 0 - success # * - error echo "dev version: " $1 $4 $3 "dev" - - local sdir="$1" - - set_changelog "$1" "$2" "$3" "$5" - set_version "$1" "$4" "$3" "dev" - - status_stage "==> Adding new UNRELEASED label in CHANGELOG.md" - add_unreleased_to_changelog "${sdir}" || return 1 + set_version "$1" "$4" "$3" "dev" "docker.mirror.hashicorp.services\/hashicorppreview\/consul-k8s-control-plane:" return 0 } From cc79bd232fe2e095f219d507e5e6831ab377b6bb Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Tue, 28 Feb 2023 23:53:41 +0000 Subject: [PATCH 211/235] backport of commit fa4c4be28e47ceecfc729b66732be7cf98fed145 --- .release/security-scan.hcl | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl index 994e169dd9..516ae4f5e6 100644 --- a/.release/security-scan.hcl +++ b/.release/security-scan.hcl @@ -1,14 +1,13 @@ container { - dependencies = false - alpine_secdb = false - secrets = false + dependencies = true + alpine_secdb = true + secrets = true } binary { - secrets = false - go_modules = false - osv = false + secrets = true + go_modules = true + osv = true oss_index = false nvd = false -} - +} \ No newline at end of file From e8f653b449fae61650bc1ec43b31afeda8c59c91 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Wed, 1 Mar 2023 23:23:12 +0000 Subject: [PATCH 212/235] backport of commit b68593fb74dc2a38d28f986aa9e576665de62151 --- control-plane/subcommand/tls-init/command_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/control-plane/subcommand/tls-init/command_test.go b/control-plane/subcommand/tls-init/command_test.go index 33493bba16..ae3cbd8982 100644 --- a/control-plane/subcommand/tls-init/command_test.go +++ b/control-plane/subcommand/tls-init/command_test.go @@ -395,7 +395,9 @@ func TestRun_CreatesServerCertificatesWithExpiryWithinSpecifiedDays(t *testing.T certBlock, _ := pem.Decode(newServerCert) certificate, err := x509.ParseCertificate(certBlock.Bytes) require.NoError(t, err) - require.Equal(t, time.Now().AddDate(1, 0, 0).Unix(), certificate.NotAfter.Unix()) + + // Add 365 days instead of 1 year to account for leap years + require.Equal(t, time.Now().AddDate(0, 0, 365).Unix(), certificate.NotAfter.Unix()) } func TestRun_CreatesServerCertificatesWithProvidedHosts(t *testing.T) { From 0ebca1b55f4bc8a515c45a7624ac9e7f82ef3ba7 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Thu, 2 Mar 2023 17:16:19 +0000 Subject: [PATCH 213/235] backport of commit a020048908eb0b68d81842ac4f1617ab6234192b --- .release/security-scan.hcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.release/security-scan.hcl b/.release/security-scan.hcl index 516ae4f5e6..42576d29b2 100644 --- a/.release/security-scan.hcl +++ b/.release/security-scan.hcl @@ -6,7 +6,7 @@ container { binary { secrets = true - go_modules = true + go_modules = false osv = true oss_index = false nvd = false From 30140e86db9232ceb2cb0244cb2d694eb9cf4994 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Thu, 2 Mar 2023 13:08:39 -0800 Subject: [PATCH 214/235] updated go version to fix cve https://go.dev/issue/58001 (#1975) * updated go version to fix cve https://go.dev/issue/58001 * updated go version to fix cve https://go.dev/issue/58001 - updated go version to use 1.19 everywhere * update to remove deprecated ioutil --- .changelog/1975.txt | 11 +++++++++++ .circleci/config.yml | 8 ++++---- .go-version | 2 +- acceptance/go.mod | 2 +- charts/consul/test/docker/Test.dockerfile | 2 +- charts/go.mod | 2 +- cli/go.mod | 2 +- control-plane/cni/go.mod | 2 +- control-plane/go.mod | 2 +- .../subcommand/install-cni/cniconfig_test.go | 14 +++++++------- .../subcommand/install-cni/command_test.go | 7 +++---- control-plane/subcommand/install-cni/kubeconfig.go | 3 +-- .../subcommand/install-cni/kubeconfig_test.go | 4 ++-- hack/aws-acceptance-test-cleanup/go.mod | 2 +- hack/copy-crds-to-chart/go.mod | 2 +- hack/helm-reference-gen/go.mod | 2 +- 16 files changed, 38 insertions(+), 29 deletions(-) create mode 100644 .changelog/1975.txt diff --git a/.changelog/1975.txt b/.changelog/1975.txt new file mode 100644 index 0000000000..ba26b1ab1e --- /dev/null +++ b/.changelog/1975.txt @@ -0,0 +1,11 @@ +```release-note:security +upgrade to use Go 1.19.6. This resolves vulnerabilities CVE-2022-41724 in crypto/tls and CVE-2022-41723 in net/http. +``` + +```release-note:improvement +cli: update minimum go version for project to 1.19. +``` + +```release-note:improvement +control-plane: update minimum go version for project to 1.19. +``` \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml index 05f6a209e9..11517a6c43 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,7 +6,7 @@ orbs: executors: go: docker: - - image: docker.mirror.hashicorp.services/cimg/go:1.18.3 + - image: docker.mirror.hashicorp.services/cimg/go:1.19.6 environment: TEST_RESULTS: /tmp/test-results # path to where test results are saved @@ -34,9 +34,9 @@ commands: - run: name: Install go, gotestsum, kind, kubectl, and helm command: | - wget https://golang.org/dl/go1.18.3.linux-amd64.tar.gz - sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.18.3.linux-amd64.tar.gz - rm go1.18.3.linux-amd64.tar.gz + wget https://golang.org/dl/go1.19.6.linux-amd64.tar.gz + sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.19.6.linux-amd64.tar.gz + rm go1.19.6.linux-amd64.tar.gz echo 'export PATH=$PATH:/usr/local/go/bin' >> $BASH_ENV wget https://github.com/gotestyourself/gotestsum/releases/download/v1.6.4/gotestsum_1.6.4_linux_amd64.tar.gz diff --git a/.go-version b/.go-version index b9fb27ab4f..2a4feaf54c 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.18.3 +1.19.6 diff --git a/acceptance/go.mod b/acceptance/go.mod index b7b11bc27c..5c8893cac5 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/consul-k8s/acceptance -go 1.18 +go 1.19 require ( github.com/gruntwork-io/terratest v0.31.2 diff --git a/charts/consul/test/docker/Test.dockerfile b/charts/consul/test/docker/Test.dockerfile index d60e8b0a24..c9351259c2 100644 --- a/charts/consul/test/docker/Test.dockerfile +++ b/charts/consul/test/docker/Test.dockerfile @@ -6,7 +6,7 @@ # a script to configure kubectl, potentially install Helm, and run the tests # manually. This image only has the dependencies pre-installed. -FROM cimg/go:1.18 +FROM cimg/go:1.19 # change the user to root so we can install stuff USER root diff --git a/charts/go.mod b/charts/go.mod index 9c001ddad8..cdb23e46b0 100644 --- a/charts/go.mod +++ b/charts/go.mod @@ -1,3 +1,3 @@ module github.com/hashicorp/consul-k8s/charts -go 1.18 +go 1.19 diff --git a/cli/go.mod b/cli/go.mod index cd95397863..3151328406 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/consul-k8s/cli -go 1.18 +go 1.19 require ( github.com/bgentry/speakeasy v0.1.0 diff --git a/control-plane/cni/go.mod b/control-plane/cni/go.mod index 660b720d43..7b97f5d07f 100644 --- a/control-plane/cni/go.mod +++ b/control-plane/cni/go.mod @@ -52,4 +52,4 @@ require ( replace github.com/hashicorp/consul/sdk v0.9.0 => github.com/hashicorp/consul/sdk v0.4.1-0.20220531155537-364758ef2f50 -go 1.18 +go 1.19 diff --git a/control-plane/go.mod b/control-plane/go.mod index 8dd66de28d..e72be74610 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -129,4 +129,4 @@ require ( sigs.k8s.io/yaml v1.2.0 // indirect ) -go 1.18 +go 1.19 diff --git a/control-plane/subcommand/install-cni/cniconfig_test.go b/control-plane/subcommand/install-cni/cniconfig_test.go index 640b9d93cb..b6e2154adb 100644 --- a/control-plane/subcommand/install-cni/cniconfig_test.go +++ b/control-plane/subcommand/install-cni/cniconfig_test.go @@ -2,7 +2,7 @@ package installcni import ( "fmt" - "io/ioutil" + "os" "path/filepath" "testing" @@ -93,10 +93,10 @@ func TestConfListFromConfFile(t *testing.T) { actualFile, err := confListFileFromConfFile(tempCfgFile) require.NoError(t, err) - actual, err := ioutil.ReadFile(actualFile) + actual, err := os.ReadFile(actualFile) require.NoError(t, err) - expected, err := ioutil.ReadFile(expectedCfgFile) + expected, err := os.ReadFile(expectedCfgFile) require.NoError(t, err) require.Equal(t, string(expected), string(actual)) @@ -168,10 +168,10 @@ func TestAppendCNIConfig(t *testing.T) { err = appendCNIConfig(c.consulConfig, tempDestFile) require.NoError(t, err) - actual, err := ioutil.ReadFile(tempDestFile) + actual, err := os.ReadFile(tempDestFile) require.NoError(t, err) - expected, err := ioutil.ReadFile(c.goldenFile) + expected, err := os.ReadFile(c.goldenFile) require.NoError(t, err) require.Equal(t, string(expected), string(actual)) @@ -298,10 +298,10 @@ func TestRemoveCNIConfig(t *testing.T) { t.Fatal(err) } - actual, err := ioutil.ReadFile(tempDestFile) + actual, err := os.ReadFile(tempDestFile) require.NoError(t, err) - expected, err := ioutil.ReadFile(c.cfgFile) + expected, err := os.ReadFile(c.cfgFile) require.NoError(t, err) require.Equal(t, string(expected), string(actual)) diff --git a/control-plane/subcommand/install-cni/command_test.go b/control-plane/subcommand/install-cni/command_test.go index a7e97a4aa9..5cb9bea91e 100644 --- a/control-plane/subcommand/install-cni/command_test.go +++ b/control-plane/subcommand/install-cni/command_test.go @@ -3,7 +3,6 @@ package installcni import ( "context" "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -65,11 +64,11 @@ func TestRun_DirectoryWatcher(t *testing.T) { require.NoError(t, err) time.Sleep(50 * time.Millisecond) // The golden file contains the consul config. - expected, err := ioutil.ReadFile(goldenFile) + expected, err := os.ReadFile(goldenFile) require.NoError(t, err) // Get the name of the config file in the tempDir and read it. tempDestFile := filepath.Join(tempDir, configFile) - actual, err := ioutil.ReadFile(tempDestFile) + actual, err := os.ReadFile(tempDestFile) require.NoError(t, err) // Filewatcher should have detected a change and appended to the config file. Make sure // files match. @@ -82,7 +81,7 @@ func TestRun_DirectoryWatcher(t *testing.T) { require.NoError(t, err) time.Sleep(50 * time.Millisecond) // Re-read the config file so we can compare the updated config file. - actual, err = ioutil.ReadFile(tempDestFile) + actual, err = os.ReadFile(tempDestFile) require.NoError(t, err) // Filewatcher should have detected change, fixed and appended to the config file. Make sure // files match. diff --git a/control-plane/subcommand/install-cni/kubeconfig.go b/control-plane/subcommand/install-cni/kubeconfig.go index e611828e36..ca93759578 100644 --- a/control-plane/subcommand/install-cni/kubeconfig.go +++ b/control-plane/subcommand/install-cni/kubeconfig.go @@ -3,7 +3,6 @@ package installcni import ( "errors" "fmt" - "io/ioutil" "os" "path/filepath" @@ -120,7 +119,7 @@ func serviceAccountToken(tokenPath string) (string, error) { if _, err := os.Stat(tokenPath); errors.Is(err, os.ErrNotExist) { return "", fmt.Errorf("tokenPath does not exist: %w", err) } - token, err := ioutil.ReadFile(tokenPath) + token, err := os.ReadFile(tokenPath) if err != nil { return "", fmt.Errorf("could not read service account token: %w", err) } diff --git a/control-plane/subcommand/install-cni/kubeconfig_test.go b/control-plane/subcommand/install-cni/kubeconfig_test.go index 22a7eae9b1..899ad3f600 100644 --- a/control-plane/subcommand/install-cni/kubeconfig_test.go +++ b/control-plane/subcommand/install-cni/kubeconfig_test.go @@ -1,7 +1,7 @@ package installcni import ( - "io/ioutil" + "os" "path/filepath" "testing" @@ -39,7 +39,7 @@ func TestKubeConfigYaml(t *testing.T) { require.NoError(t, err) golden := filepath.Join("testdata", c.goldenFile) - expected, err := ioutil.ReadFile(golden) + expected, err := os.ReadFile(golden) require.NoError(t, err) require.Equal(t, string(expected), string(actual)) diff --git a/hack/aws-acceptance-test-cleanup/go.mod b/hack/aws-acceptance-test-cleanup/go.mod index a266c1a7e8..13e8f48909 100644 --- a/hack/aws-acceptance-test-cleanup/go.mod +++ b/hack/aws-acceptance-test-cleanup/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/consul-helm/hack/aws-acceptance-test-cleanup -go 1.18 +go 1.19 require ( github.com/aws/aws-sdk-go v1.38.63 diff --git a/hack/copy-crds-to-chart/go.mod b/hack/copy-crds-to-chart/go.mod index 5456f28ce2..73b1f10306 100644 --- a/hack/copy-crds-to-chart/go.mod +++ b/hack/copy-crds-to-chart/go.mod @@ -1,3 +1,3 @@ module github.com/hashicorp/consul-k8s/hack/copy-crds-to-chart -go 1.18 +go 1.19 diff --git a/hack/helm-reference-gen/go.mod b/hack/helm-reference-gen/go.mod index 8595831de1..7e41675f18 100644 --- a/hack/helm-reference-gen/go.mod +++ b/hack/helm-reference-gen/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/consul-k8s/hack/helm-reference-gen -go 1.18 +go 1.19 require ( github.com/stretchr/testify v1.6.1 From 098f2c710c6d4652092e48864de0a14f8a5ee722 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Fri, 3 Mar 2023 08:39:22 -0800 Subject: [PATCH 215/235] added changelog files (#1981) - removed unreleased section, we'll now be generating changelog entries as part of the release process --- .changelog/1770.txt | 3 +++ .changelog/1914.txt | 3 +++ .changelog/1934.txt | 3 +++ CHANGELOG.md | 6 ------ 4 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 .changelog/1770.txt create mode 100644 .changelog/1914.txt create mode 100644 .changelog/1934.txt diff --git a/.changelog/1770.txt b/.changelog/1770.txt new file mode 100644 index 0000000000..f8b1c570da --- /dev/null +++ b/.changelog/1770.txt @@ -0,0 +1,3 @@ +```release-note:improvement +control-plane: server ACL Init always appends both, the secrets from the serviceAccount's secretRefs and the one created by the Helm chart, to support Openshift secret handling. +``` \ No newline at end of file diff --git a/.changelog/1914.txt b/.changelog/1914.txt new file mode 100644 index 0000000000..3179f3b0b3 --- /dev/null +++ b/.changelog/1914.txt @@ -0,0 +1,3 @@ +```release-note:bug +control-plane: fix issue where consul-connect-injector acl token was unintentionally being deleted and not recreated when a container was restarted due to a livenessProbe failure. +``` \ No newline at end of file diff --git a/.changelog/1934.txt b/.changelog/1934.txt new file mode 100644 index 0000000000..a8bc41fd50 --- /dev/null +++ b/.changelog/1934.txt @@ -0,0 +1,3 @@ +```release-note:improvement +control-plane: update alpine to 3.17 in the Docker image. +``` \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9bd8714c8e..df9aab2660 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,3 @@ -## UNRELEASED - -IMPROVEMENTS: -* Control Plane - * Update alpine to 3.17 in the Docker image. [[GH-1934](https://github.com/hashicorp/consul-k8s/pull/1934)] - ## 0.49.4 (February 7, 2023) BREAKING CHANGES: From 8fb45e8eaee99aabc660fc2fd6fe433532eb8dcb Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Fri, 3 Mar 2023 19:03:16 +0000 Subject: [PATCH 216/235] backport of commit c740fed147777c756d474c6cfcf9a38089f40312 --- .github/workflows/changelog-checker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index bb13255d29..ae2e88170b 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -14,7 +14,7 @@ on: jobs: # checks that a .changelog entry is present for a PR changelog-check: - # If there a `pr/no-changelog` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` + # If there's a `pr/no-changelog` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-changelog') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" runs-on: ubuntu-latest @@ -39,7 +39,7 @@ jobs: # If we do not find a file in .changelog/, we fail the check if [ -z "$changelog_files" ]; then # Fail status check when no .changelog entry was found on the PR - echo "Did not find a .changelog entry ${enforce_matching_pull_request_number}and the 'pr/no-changelog' label was not applied. Reference - https://github.com/hashicorp/consul/pull/8387" + echo "Did not find a .changelog entry ${enforce_matching_pull_request_number}and the 'pr/no-changelog' label was not applied. Reference - https://github.com/hashicorp/consul-k8s/pull/1947" exit 1 else echo "Found .changelog entry in PR!" From fa3e9b9a1c3131f02e31faab45225cb849008d05 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson Date: Fri, 3 Mar 2023 19:03:07 +0000 Subject: [PATCH 217/235] backport of commit d482dd990fda1e0199424f6c9cf4579c7a20f6f5 --- .github/workflows/backport-checker.yml | 32 ++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .github/workflows/backport-checker.yml diff --git a/.github/workflows/backport-checker.yml b/.github/workflows/backport-checker.yml new file mode 100644 index 0000000000..5bcac5a38e --- /dev/null +++ b/.github/workflows/backport-checker.yml @@ -0,0 +1,32 @@ +# This workflow checks that there is either a 'pr/no-backport' label applied to a PR +# or there is a backport/.txt file associated with a PR for a backport label + +name: Backport Checker + +on: + pull_request: + types: [opened, synchronize, labeled] + # Runs on PRs to main and all release branches + branches: + - main + - release/* + +jobs: + # checks that a backport label is present for a PR + backport-check: + # If there's a `pr/no-backport` label we ignore this check. Also, we ignore PRs created by the bot assigned to `backport-assistant` + if: "! ( contains(github.event.pull_request.labels.*.name, 'pr/no-backport') || github.event.pull_request.user.login == 'hc-github-team-consul-core' )" + runs-on: ubuntu-latest + + steps: + - name: Check for Backport Label + run: | + labels="${{join(github.event.pull_request.labels.*.name, ', ') }}" + if [[ "$labels" =~ .*"backport/".* ]]; then + echo "Found backport label!" + exit 0 + fi + # Fail status check when no backport label was found on the PR + echo "Did not find a backport label matching the pattern 'backport/*' and the 'pr/no-backport' label was not applied. Reference - https://github.com/hashicorp/consul-k8s/pull/1982" + exit 1 + From fea09c4cf6c41321dcf74e0cffc1d869c25785a7 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Tue, 7 Mar 2023 22:56:29 -0800 Subject: [PATCH 218/235] update to consul 1.13.7 (#1993) --- charts/consul/Chart.yaml | 4 ++-- charts/consul/values.yaml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index a6c19db870..7982d7a899 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 name: consul version: 0.49.5-dev -appVersion: 1.13.6 +appVersion: 1.13.7 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart home: https://www.consul.io @@ -13,7 +13,7 @@ annotations: artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul - image: hashicorp/consul:1.13.6 + image: hashicorp/consul:1.13.7 - name: consul-k8s-control-plane image: hashicorp/consul-k8s-control-plane:0.49.5-dev - name: envoy diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 46a565a948..6c33f9c46d 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -109,7 +109,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.13.6" + image: "hashicorp/consul:1.13.7" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. From cdbb841530e833b811a4a19ae84141e6f2ee7a27 Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Wed, 8 Mar 2023 09:56:21 -0800 Subject: [PATCH 219/235] ready for 0.49.5 release (#2000) --- CHANGELOG.md | 17 +++++++++++++++++ charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df9aab2660..02375a2ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,20 @@ +## 0.49.5 (March 9, 2023) + +SECURITY: + +* upgrade to use Go 1.19.6. This resolves vulnerabilities CVE-2022-41724 in crypto/tls and CVE-2022-41723 in net/http. [[GH-1975](https://github.com/hashicorp/consul-k8s/issues/1975)] + +IMPROVEMENTS: + +* cli: update minimum go version for project to 1.19. [[GH-1975](https://github.com/hashicorp/consul-k8s/issues/1975)] +* control-plane: server ACL Init always appends both, the secrets from the serviceAccount's secretRefs and the one created by the Helm chart, to support Openshift secret handling. [[GH-1770](https://github.com/hashicorp/consul-k8s/issues/1770)] +* control-plane: update alpine to 3.17 in the Docker image. [[GH-1934](https://github.com/hashicorp/consul-k8s/issues/1934)] +* control-plane: update minimum go version for project to 1.19. [[GH-1975](https://github.com/hashicorp/consul-k8s/issues/1975)] + +BUG FIXES: + +* control-plane: fix issue where consul-connect-injector acl token was unintentionally being deleted and not recreated when a container was restarted due to a livenessProbe failure. [[GH-1914](https://github.com/hashicorp/consul-k8s/issues/1914)] + ## 0.49.4 (February 7, 2023) BREAKING CHANGES: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 7982d7a899..977f107ea0 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.5-dev +version: 0.49.5 appVersion: 1.13.7 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: true + artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.7 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.5-dev + image: hashicorp/consul-k8s-control-plane:0.49.5 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 6c33f9c46d..23b32bbadf 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.5-dev + imageK8S: hashicorp/consul-k8s-control-plane:0.49.5 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index f89582cd9d..8b842b3976 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index f89582cd9d..8b842b3976 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From f78bfb1ec846ed240f385ac7fa07415fe778856d Mon Sep 17 00:00:00 2001 From: Michael Wilkerson <62034708+wilkermichael@users.noreply.github.com> Date: Thu, 9 Mar 2023 11:19:16 -0800 Subject: [PATCH 220/235] ready for 0.49.6 dev (#2004) --- charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 977f107ea0..ccc02a74db 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.5 +version: 0.49.6-dev appVersion: 1.13.7 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: false + artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.7 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.5 + image: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:0.49.6-dev - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 23b32bbadf..90b4493048 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.5 + imageK8S: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:0.49.6-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 8b842b3976..e63f0dde27 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.5" + Version = "0.49.6" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 8b842b3976..e63f0dde27 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.5" + Version = "0.49.6" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From 051d84cd02e5f71de9e1a0e44854d64265587ada Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Wed, 15 Mar 2023 14:28:31 -0700 Subject: [PATCH 221/235] Backport of values.yaml - set default connect inject init cpu resource limits to `null` to increase service registration times into release/0.49.x (#2019) * backport of commit 7a99af0dbf57eb20e921c7997e1a38460949d88e --------- Co-authored-by: David Yu --- .changelog/2008.txt | 3 ++ .../test/unit/connect-inject-deployment.bats | 5 +-- charts/consul/values.yaml | 34 ++++++++++++++----- 3 files changed, 29 insertions(+), 13 deletions(-) create mode 100644 .changelog/2008.txt diff --git a/.changelog/2008.txt b/.changelog/2008.txt new file mode 100644 index 0000000000..ba8bb5fa25 --- /dev/null +++ b/.changelog/2008.txt @@ -0,0 +1,3 @@ +```release-note:improvement +helm: Set default `limits.cpu` resource setting to `null` for `consul-connect-inject-init` container to speed up registration times when onboarding services onto the mesh during the init container lifecycle. +``` diff --git a/charts/consul/test/unit/connect-inject-deployment.bats b/charts/consul/test/unit/connect-inject-deployment.bats index b84efc0808..0dfad94e93 100755 --- a/charts/consul/test/unit/connect-inject-deployment.bats +++ b/charts/consul/test/unit/connect-inject-deployment.bats @@ -1280,10 +1280,7 @@ EOF local actual=$(echo "$cmd" | yq 'any(contains("-init-container-memory-limit=150Mi"))' | tee /dev/stderr) [ "${actual}" = "true" ] - - local actual=$(echo "$cmd" | - yq 'any(contains("-init-container-cpu-limit=50m"))' | tee /dev/stderr) - [ "${actual}" = "true" ] + } @test "connectInject/Deployment: can set init container resources" { diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 90b4493048..e44f1ba507 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -2137,15 +2137,22 @@ connectInject: # @type: string annotations: null - # The resource settings for connect inject pods. - # @recurse: false + # The resource settings for connect inject pods. The defaults, are optimized for getting started worklows on developer deployments. The settings should be tweaked for production deployments. # @type: map resources: requests: + # Recommended production default: 500Mi + # @type: string memory: "50Mi" + # Recommended production default: 250m + # @type: string cpu: "50m" limits: + # Recommended production default: 500Mi + # @type: string memory: "50Mi" + # Recommended production default: 250m + # @type: string cpu: "50m" # Sets the failurePolicy for the mutating webhook. By default this will cause pods not part of the consul installation to fail scheduling while the webhook @@ -2313,31 +2320,40 @@ connectInject: # @type: map resources: requests: - # Recommended default: 100Mi + # Recommended production default: 100Mi # @type: string memory: null - # Recommended default: 100m + # Recommended production default: 100m # @type: string cpu: null limits: - # Recommended default: 100Mi + # Recommended production default: 100Mi # @type: string memory: null - # Recommended default: 100m + # Recommended production default: 100m # @type: string cpu: null - # The resource settings for the Connect injected init container. - # @recurse: false + # The resource settings for the Connect injected init container. If null, the resources + # won't be set for the initContainer. The defaults are optimized for developer instances of + # Kubernetes, however they should be tweaked with the recommended defaults as shown below to speed up service registration times. # @type: map initContainer: resources: requests: + # Recommended production default: 150Mi + # @type: string memory: "25Mi" + # Recommended production default: 250m + # @type: string cpu: "50m" limits: + # Recommended production default: 150Mi + # @type: string memory: "150Mi" - cpu: "50m" + # Recommended production default: 500m + # @type: string + cpu: null # Controller handles config entry custom resources. # Requires consul >= 1.8.4. From 458339f5b643ae0c3703a800fbcb9a54880570b2 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Tue, 4 Apr 2023 20:31:44 +0000 Subject: [PATCH 222/235] backport of commit b89d4aa53979cd91eca159444f9b4035779781f5 --- charts/consul/values.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index e44f1ba507..c2b81c1ea1 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -3066,7 +3066,7 @@ apiGateway: # ```yaml # service: # annotations: | - # - external-dns.alpha.kubernetes.io/hostname + # - external-dns.alpha.kubernetes.io/hostname # ``` # # @type: string From 43146c57f932361756e66d2c71e7f87173f68897 Mon Sep 17 00:00:00 2001 From: Curt Bushko Date: Mon, 17 Apr 2023 13:27:58 -0400 Subject: [PATCH 223/235] Sync GHA release 0.49.x from main (#2058) --- .circleci/config.yml | 1417 ----------------- .github/workflows/jira-issues.yaml | 85 + .github/workflows/jira-pr.yaml | 99 ++ .github/workflows/merge.yml | 31 + .github/workflows/nightly-acceptance.yml | 27 + .github/workflows/pr.yml | 26 + .github/workflows/reusable-acceptance.yml | 128 -- .github/workflows/reusable-golangci-lint.yml | 34 - .github/workflows/reusable-unit.yml | 57 - .github/workflows/test.yml | 342 ---- .../workflows/weekly-acceptance-0-49-x.yml | 29 + .github/workflows/weekly-acceptance-1-0-x.yml | 30 + .github/workflows/weekly-acceptance-1-1-x.yml | 30 + 13 files changed, 357 insertions(+), 1978 deletions(-) delete mode 100644 .circleci/config.yml create mode 100644 .github/workflows/jira-issues.yaml create mode 100644 .github/workflows/jira-pr.yaml create mode 100644 .github/workflows/merge.yml create mode 100644 .github/workflows/nightly-acceptance.yml create mode 100644 .github/workflows/pr.yml delete mode 100644 .github/workflows/reusable-acceptance.yml delete mode 100644 .github/workflows/reusable-golangci-lint.yml delete mode 100644 .github/workflows/reusable-unit.yml delete mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/weekly-acceptance-0-49-x.yml create mode 100644 .github/workflows/weekly-acceptance-1-0-x.yml create mode 100644 .github/workflows/weekly-acceptance-1-1-x.yml diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 11517a6c43..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,1417 +0,0 @@ -# Originally from consul-k8s -version: 2.1 -orbs: - slack: circleci/slack@3.4.2 -# reusable 'executor' object for jobs -executors: - go: - docker: - - image: docker.mirror.hashicorp.services/cimg/go:1.19.6 - environment: - TEST_RESULTS: /tmp/test-results # path to where test results are saved - -slack-channel: &slack-channel C0421KHNAV9 #feed-consul-k8s-ci channel ID -control-plane-path: &control-plane-path control-plane -cli-path: &cli-path cli -acceptance-mod-path: &acceptance-mod-path acceptance -acceptance-test-path: &acceptance-test-path acceptance/tests -acceptance-framework-path: &acceptance-framework-path acceptance/framework -helm-gen-path: &helm-gen-path hack/helm-reference-gen -gke-terraform-path: &gke-terraform-path charts/consul/test/terraform/gke -eks-terraform-path: &eks-terraform-path charts/consul/test/terraform/eks -aks-terraform-path: &aks-terraform-path charts/consul/test/terraform/aks -openshift-terraform-path: &openshift-terraform-path charts/consul/test/terraform/openshift -# This image is built from charts/consul/test/docker/Test.dockerfile and provides the necessary dependencies for running on our cloud targets. -consul-helm-test-image: &consul-helm-test-image docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.3 - -######################## -# COMMANDS -######################## -# Commands define a sequence of steps as a map to be executed and reused in jobs -commands: - install-prereqs: - steps: - - run: - name: Install go, gotestsum, kind, kubectl, and helm - command: | - wget https://golang.org/dl/go1.19.6.linux-amd64.tar.gz - sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.19.6.linux-amd64.tar.gz - rm go1.19.6.linux-amd64.tar.gz - echo 'export PATH=$PATH:/usr/local/go/bin' >> $BASH_ENV - - wget https://github.com/gotestyourself/gotestsum/releases/download/v1.6.4/gotestsum_1.6.4_linux_amd64.tar.gz - sudo tar -C /usr/local/bin -xzf gotestsum_1.6.4_linux_amd64.tar.gz - rm gotestsum_1.6.4_linux_amd64.tar.gz - - curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.15.0/kind-linux-amd64 - chmod +x ./kind - sudo mv ./kind /usr/local/bin/kind - - curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl" - chmod +x ./kubectl - sudo mv ./kubectl /usr/local/bin/kubectl - - wget https://get.helm.sh/helm-v3.7.0-linux-amd64.tar.gz - tar -zxvf helm-v3.7.0-linux-amd64.tar.gz - sudo mv linux-amd64/helm /usr/local/bin/helm - custom-checkout: - description: | - custom-checkout will perform a custom checkout procedure if provided with an alternative git reference, - otherwise it will run the CircleCI defined checkout command. This is needed as the CircleCI defined checkout - command does not support subsequent git actions after being called. - parameters: - git-ref: - type: string - default: "" - steps: - - when: - condition: << parameters.git-ref >> - steps: - - run: - name: Checkout code - command: | - ssh-keyscan github.com >> ~/.ssh/known_hosts - if [ -e '/home/circleci/project/.git' ] ; then - echo 'Fetching into existing repository' - existing_repo='true' - cd '/home/circleci/project' - git remote set-url origin "$CIRCLE_REPOSITORY_URL" || true - else - echo 'Cloning git repository' - existing_repo='false' - mkdir -p '/home/circleci/project' - cd '/home/circleci/project' - git clone --no-checkout "$CIRCLE_REPOSITORY_URL" . - fi - - if [ "$existing_repo" = 'true' ] || [ 'false' = 'true' ]; then - echo 'Fetching from remote repository' - git fetch --force origin - git fetch --force --tags origin - fi - - echo 'Checking out branch/tag' - git checkout --force "<< parameters.git-ref >>" - - unless: - condition: << parameters.git-ref >> - steps: - - checkout - create-kind-clusters: - parameters: - version: - type: string - steps: - - run: - name: Create kind clusters - command: | - kind create cluster --name dc1 --image kindest/node:<< parameters.version >> - kind create cluster --name dc2 --image kindest/node:<< parameters.version >> - create-kind-cni-clusters: - parameters: - version: - type: string - steps: - - run: - name: Create CNI kind clusters - command: | - kind create cluster --config=acceptance/framework/environment/cni-kind/kind.config --name dc1 --image kindest/node:<< parameters.version >> - make kind-cni-calico - kind create cluster --config=acceptance/framework/environment/cni-kind/kind.config --name dc2 --image kindest/node:<< parameters.version >> - make kind-cni-calico - build-cli: - steps: - - run: - name: Build consul-k8s CLI - working_directory: *cli-path - command: | - go build -o ./bin/consul-k8s - sudo cp ./bin/consul-k8s /usr/local/go/bin/ - consul-k8s version - - run-acceptance-tests: - description: | - Runs the Kind acceptance tests using a provided consul-k8s image, or else attempts to use the image referenced by the - branch name and git reference of the current git commit - parameters: - failfast: - type: boolean - default: false - additional-flags: - type: string - consul-k8s-image: - type: string - default: "docker.mirror.hashicorp.services/hashicorpdev/consul-k8s-control-plane:$(git rev-parse --short HEAD)" - go-path: - type: string - default: "/home/circleci/.go_workspace" - steps: - - when: - condition: << parameters.failfast >> - steps: - - run: - name: Run acceptance tests - working_directory: *acceptance-test-path - no_output_timeout: 2h - command: | - # Enterprise tests can't run on fork PRs because they require - # a secret. - if [ -z "$CIRCLE_PR_NUMBER" ]; then - ENABLE_ENTERPRISE=true - fi - - # We have to run the tests for each package separately so that we can - # exit early if any test fails (-failfast only works within a single - # package). - exit_code=0 - pkgs=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname) - echo "Running $(echo $pkgs | wc -w) packages:" - echo $pkgs - for pkg in $pkgs - do - if ! gotestsum --no-summary=all --jsonfile=jsonfile-${pkg////-} -- $pkg -p 1 -timeout 2h -failfast \ - << parameters.additional-flags >> \ - ${ENABLE_ENTERPRISE:+-enable-enterprise} \ - -enable-multi-cluster \ - -debug-directory="$TEST_RESULTS/debug" \ - -consul-k8s-image=<< parameters.consul-k8s-image >> - then - echo "Tests in ${pkg} failed, aborting early" - exit_code=1 - break - fi - done - gotestsum --raw-command --junitfile "$TEST_RESULTS/gotestsum-report.xml" -- cat jsonfile* - exit $exit_code - - - unless: - condition: << parameters.failfast >> - steps: - - run: - name: Run acceptance tests - working_directory: *acceptance-test-path - no_output_timeout: 2h - command: | - # Enterprise tests can't run on fork PRs because they require - # a secret. - if [ -z "$CIRCLE_PR_NUMBER" ]; then - ENABLE_ENTERPRISE=true - fi - - pkgs=$(go list ./... | circleci tests split --split-by=timings --timings-type=classname) - echo "Running $pkgs" - gotestsum --junitfile "$TEST_RESULTS/gotestsum-report.xml" -- $pkgs -p 1 -timeout 2h -failfast \ - << parameters.additional-flags >> \ - ${ENABLE_ENTERPRISE:+-enable-enterprise} \ - -enable-multi-cluster \ - -debug-directory="$TEST_RESULTS/debug" \ - -consul-k8s-image=<< parameters.consul-k8s-image >> - -######################## -# JOBS -######################## -# Jobs are a collection of steps. These are used in the workflows to define -# what gets run in the pipeline -jobs: - go-fmt-and-vet-control-plane: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-k8s-modcache-v2-{{ checksum "control-plane/go.mod" }} - - - run: - name: go mod download - working_directory: *control-plane-path - command: go mod download - - # Save go module cache if the go.mod file has changed - - save_cache: - key: consul-k8s-modcache-v2-{{ checksum "control-plane/go.mod" }} - paths: - - "/home/circleci/go/pkg/mod" - - # check go fmt output because it does not report non-zero when there are fmt changes - - run: - name: check go fmt - working_directory: *control-plane-path - command: | - files=$(go fmt ./...) - if [ -n "$files" ]; then - echo "The following file(s) do not conform to go fmt:" - echo "$files" - exit 1 - fi - - run: cd control-plane && go vet ./... - - lint-control-plane: - executor: go - steps: - - checkout - - run: go get -u github.com/hashicorp/lint-consul-retry && lint-consul-retry - - run: - name: run lint - working_directory: *control-plane-path - command: go run hack/lint-api-new-client/main.go - - test-control-plane: - executor: go - environment: - TEST_RESULTS: /tmp/test-results - parallelism: 1 - steps: - - checkout - - run: mkdir -p $TEST_RESULTS - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-k8s-modcache-v2-{{ checksum "control-plane/go.mod" }} - - # run go tests with gotestsum - - run: - name: run go tests - working_directory: *control-plane-path - command: | - # download and install the consul binary - wget https://releases.hashicorp.com/consul/"${CONSUL_VERSION}"/consul_"${CONSUL_VERSION}"_linux_amd64.zip && \ - unzip consul_"${CONSUL_VERSION}"_linux_amd64.zip -d /home/circleci/bin && - rm consul_"${CONSUL_VERSION}"_linux_amd64.zip - PACKAGE_NAMES=$(go list ./...) - gotestsum --junitfile $TEST_RESULTS/gotestsum-report.xml -- -p 4 $PACKAGE_NAMES - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - test-enterprise-control-plane: - executor: go - environment: - TEST_RESULTS: /tmp/test-results - parallelism: 1 - steps: - - checkout - - run: mkdir -p $TEST_RESULTS - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-k8s-modcache-v2-{{ checksum "control-plane/go.mod" }} - - # run go tests with gotestsum - - run: - name: run enterprise go tests - working_directory: *control-plane-path - command: | - # download and install the consul binary - wget https://releases.hashicorp.com/consul/"${CONSUL_ENT_VERSION}"/consul_"${CONSUL_ENT_VERSION}"_linux_amd64.zip && \ - unzip consul_"${CONSUL_ENT_VERSION}"_linux_amd64.zip -d /home/circleci/bin && - rm consul_"${CONSUL_ENT_VERSION}"_linux_amd64.zip - PACKAGE_NAMES=$(go list ./...) - gotestsum --junitfile $TEST_RESULTS/gotestsum-report.xml -- -tags=enterprise -p 4 $PACKAGE_NAMES - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - build-distro: # defines a parameterized job - description: A job that will build the os/arch distro set by XC_OS and XC_ARCH - parameters: - OS: - description: What OSes to build - default: "" - type: string - ARCH: - description: What architectures to build - default: "" - type: string - executor: go - environment: - GOXPARALLEL: 2 # CircleCI containers are 2 CPU x 4GB RAM - steps: - - checkout - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-k8s-modcache-v2-{{ checksum "control-plane/go.mod" }} - - run: - name: build local - working_directory: *control-plane-path - command: XC_OS="<< parameters.OS >>" XC_ARCH="<< parameters.ARCH >>" ./build-support/scripts/build-local.sh - # persist to downstream job - - persist_to_workspace: - root: . - paths: - - control-plane/pkg/bin - - control-plane/cni/pkg/bin - # save dev build to CircleCI - - store_artifacts: - path: ./control-plane/pkg/bin - - store_artifacts: - path: ./control-plane/cni/pkg/bin - - # upload dev docker image - dev-upload-docker: - machine: - image: ubuntu-2004:202010-01 - environment: - DOCKER_CLI_EXPERIMENTAL: enabled - steps: - - checkout - # get consul-k8s binary - - attach_workspace: - at: . - - run: sudo apt-get update - - run: sudo apt-get install -y qemu-user-static - - run: docker buildx create --use - - run: - name: make ci.dev-docker - working_directory: *control-plane-path - command: make ci.dev-docker - - unit-cli: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-k8s-cli-modcache-v2-{{ checksum "cli/go.mod" }} - - - run: - name: go mod download - working_directory: *cli-path - command: go mod download - - # Save go module cache if the go.mod file has changed - - save_cache: - key: consul-k8s-cli-modcache-v2-{{ checksum "cli/go.mod" }} - paths: - - "/home/circleci/go/pkg/mod" - - - run: mkdir -p $TEST_RESULTS - - - run: - name: Run tests - working_directory: *cli-path - command: | - gotestsum --junitfile $TEST_RESULTS/gotestsum-report.xml ./... -- -p 4 - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - go-fmt-and-vet-acceptance: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - # Save go module cache if the go.mod file has changed - - save_cache: - key: consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - "/home/circleci/go/pkg/mod" - - # check go fmt output because it does not report non-zero when there are fmt changes - - run: - name: check go fmt - working_directory: *acceptance-mod-path - command: | - files=$(go fmt ./...) - if [ -n "$files" ]; then - echo "The following file(s) do not conform to go fmt:" - echo "$files" - exit 1 - fi - - - run: - name: go vet - working_directory: *acceptance-mod-path - command: go vet ./... - - go-fmt-and-vet-helm-gen: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-helm-gen-modcache-v2-{{ checksum "charts/consul/hack/helm-reference-gen/go.mod" }} - - - run: - name: go mod download - working_directory: *helm-gen-path - command: go mod download - - # Save go module cache if the go.mod file has changed - - save_cache: - key: consul-helm-helm-gen-modcache-v2-{{ checksum "charts/consul/hack/helm-reference-gen/go.mod" }} - paths: - - "/home/circleci/go/pkg/mod" - - # check go fmt output because it does not report non-zero when there are fmt changes - - run: - name: check go fmt - working_directory: *helm-gen-path - command: | - files=$(go fmt ./...) - if [ -n "$files" ]; then - echo "The following file(s) do not conform to go fmt:" - echo "$files" - exit 1 - fi - - - run: - name: go vet - working_directory: *helm-gen-path - command: go vet ./... - - unit-acceptance-framework: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run: - name: Run tests - working_directory: *acceptance-framework-path - command: | - gotestsum --junitfile $TEST_RESULTS/gotestsum-report.xml ./... -- -p 4 - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - unit-helm-gen: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-helm-gen-modcache-v2-{{ checksum "charts/consul/hack/helm-reference-gen/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run: - name: Run tests - working_directory: *helm-gen-path - command: | - gotestsum --junitfile $TEST_RESULTS/gotestsum-report.xml ./... -- -p 4 - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - validate-helm-gen: - executor: go - steps: - - checkout - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-helm-gen-modcache-v2-{{ checksum "charts/consul/hack/helm-reference-gen/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run: - name: Validate helm gen - working_directory: *helm-gen-path - command: | - go run ./... -validate - - unit-test-helm-templates: - docker: - - image: *consul-helm-test-image - - steps: - - checkout - - - run: - name: Run Unit Tests - working_directory: charts/consul - command: bats --jobs 4 ./test/unit - - ########################### - # KIND ACCEPTANCE TEST JOBS - ########################### - acceptance: - environment: - - TEST_RESULTS: /tmp/test-results - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - parallelism: 6 - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.24.4" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - build-cli - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - failfast: true - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - acceptance-tproxy: - environment: - - TEST_RESULTS: /tmp/test-results - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - parallelism: 6 - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.24.4" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - build-cli - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - failfast: true - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - acceptance-tproxy-cni: - environment: - - TEST_RESULTS: /tmp/test-results - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - parallelism: 3 - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.24.4" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - build-cli - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - failfast: true - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - ############################## - # CLEANUP CLOUD RESOURCES JOBS - ############################## - cleanup-gcp-resources: - docker: - - image: *consul-helm-test-image - steps: - - run: - name: cleanup leftover resources - command: | - echo "${GOOGLE_CREDENTIALS}" | gcloud auth activate-service-account --key-file=- - clusters=$(gcloud container clusters list --zone us-central1-a --project ${CLOUDSDK_CORE_PROJECT} --format json | jq -r '.[] | select(.name | test("^consul-k8s-\\d+$")) | .name') - for cluster in $clusters; do - echo "Deleting $cluster GKE cluster" - gcloud container clusters delete $cluster --zone us-central1-a --project ${CLOUDSDK_CORE_PROJECT} --quiet - done - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "GKE cleanup failed" - - cleanup-azure-resources: - docker: - - image: *consul-helm-test-image - steps: - - run: - name: cleanup leftover resources - command: | - az login --service-principal -u "$ARM_CLIENT_ID" -p "$ARM_CLIENT_SECRET" --tenant "$ARM_TENANT_ID" > /dev/null - resource_groups=$(az group list -o json | jq -r '.[] | select(.name | test("^consul-k8s-\\d+$")) | .name') - for group in $resource_groups; do - echo "Deleting $group resource group" - az group delete -n $group --yes - done - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "AKS cleanup failed" - - cleanup-eks-resources: - docker: - - image: *consul-helm-test-image - steps: - - checkout - - run: - name: cleanup eks resources - command: | - # Assume the role and set environment variables. - aws sts assume-role --role-arn "$AWS_ROLE_ARN" --role-session-name "consul-helm-$CIRCLE_BUILD_NUM" --duration-seconds 10800 > assume-role.json - export AWS_ACCESS_KEY_ID="$(jq -r .Credentials.AccessKeyId assume-role.json)" - export AWS_SECRET_ACCESS_KEY="$(jq -r .Credentials.SecretAccessKey assume-role.json)" - export AWS_SESSION_TOKEN="$(jq -r .Credentials.SessionToken assume-role.json)" - - make ci.aws-acceptance-test-cleanup - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "EKS cleanup failed" - - ############################# - # CLOUD ACCEPTANCE TEST JOBS - ############################# - acceptance-gke-1-23: - parallelism: 2 - environment: - - TEST_RESULTS: /tmp/test-results - - USE_GKE_GCLOUD_AUTH_PLUGIN: true - docker: - - image: *consul-helm-test-image - - steps: - - run: - name: Exit if forked PR - command: | - if [ -n "$CIRCLE_PR_NUMBER" ]; then - echo "Skipping acceptance tests for forked PRs; marking step successful." - circleci step halt - fi - - - checkout - - - build-cli - - run: - name: terraform init & apply - working_directory: *gke-terraform-path - command: | - terraform init - echo "${GOOGLE_CREDENTIALS}" | gcloud auth activate-service-account --key-file=- - - # On GKE, we're setting the build number instead of build URL because label values - # cannot contain '/'. - terraform apply \ - -var project=${CLOUDSDK_CORE_PROJECT} \ - -var init_cli=true \ - -var cluster_count=2 \ - -var labels="{\"build_number\": \"$CIRCLE_BUILD_NUM\"}" \ - -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *gke-terraform-path - command: | - terraform destroy -var project=${CLOUDSDK_CORE_PROJECT} -auto-approve - when: always - - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "GKE acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-gke-cni-1-23: - parallelism: 2 - environment: - - TEST_RESULTS: /tmp/test-results - - USE_GKE_GCLOUD_AUTH_PLUGIN: true - docker: - - image: *consul-helm-test-image - - steps: - - run: - name: Exit if forked PR - command: | - if [ -n "$CIRCLE_PR_NUMBER" ]; then - echo "Skipping acceptance tests for forked PRs; marking step successful." - circleci step halt - fi - - - checkout - - - build-cli - - run: - name: terraform init & apply - working_directory: *gke-terraform-path - command: | - terraform init - echo "${GOOGLE_CREDENTIALS}" | gcloud auth activate-service-account --key-file=- - - # On GKE, we're setting the build number instead of build URL because label values - # cannot contain '/'. - terraform apply \ - -var project=${CLOUDSDK_CORE_PROJECT} \ - -var init_cli=true \ - -var cluster_count=2 \ - -var labels="{\"build_number\": \"$CIRCLE_BUILD_NUM\"}" \ - -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -use-gke -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-pod-security-policies -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *gke-terraform-path - command: | - terraform destroy -var project=${CLOUDSDK_CORE_PROJECT} -auto-approve - when: always - - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "GKE CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-aks-1-22: - parallelism: 3 - environment: - - TEST_RESULTS: /tmp/test-results - docker: - - image: *consul-helm-test-image - - steps: - - checkout - - - build-cli - - run: - name: terraform init & apply - working_directory: *aks-terraform-path - command: | - terraform init - - terraform apply \ - -var client_id="$ARM_CLIENT_ID" \ - -var client_secret="$ARM_CLIENT_SECRET" \ - -var cluster_count=2 \ - -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" \ - -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *aks-terraform-path - command: | - terraform destroy -auto-approve - when: always - - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "AKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-aks-cni-1-22: - parallelism: 3 - environment: - - TEST_RESULTS: /tmp/test-results - docker: - - image: *consul-helm-test-image - - steps: - - checkout - - - build-cli - - run: - name: terraform init & apply - working_directory: *aks-terraform-path - command: | - terraform init - - terraform apply \ - -var client_id="$ARM_CLIENT_ID" \ - -var client_secret="$ARM_CLIENT_SECRET" \ - -var cluster_count=2 \ - -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" \ - -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *aks-terraform-path - command: | - terraform destroy -auto-approve - when: always - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "AKS CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-eks-1-21: - parallelism: 3 - environment: - - TEST_RESULTS: /tmp/test-results - docker: - - image: *consul-helm-test-image - - steps: - - checkout - - - build-cli - - run: - name: configure aws - command: | - aws configure --profile helm_user set aws_access_key_id "$AWS_ACCESS_KEY_ID" - aws configure --profile helm_user set aws_secret_access_key "$AWS_SECRET_ACCESS_KEY" - aws configure set role_arn "$AWS_ROLE_ARN" - aws configure set source_profile helm_user - - echo "unset AWS_ACCESS_KEY_ID" >> $BASH_ENV - echo "unset AWS_SECRET_ACCESS_KEY" >> $BASH_ENV - - - run: - name: terraform init & apply - working_directory: *eks-terraform-path - command: | - terraform init - - terraform apply -var cluster_count=2 -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *eks-terraform-path - command: | - terraform destroy -var cluster_count=2 -auto-approve - when: always - - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "EKS acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-eks-cni-1-21: - parallelism: 3 - environment: - - TEST_RESULTS: /tmp/test-results - docker: - - image: *consul-helm-test-image - - steps: - - checkout - - - build-cli - - run: - name: configure aws - command: | - aws configure --profile helm_user set aws_access_key_id "$AWS_ACCESS_KEY_ID" - aws configure --profile helm_user set aws_secret_access_key "$AWS_SECRET_ACCESS_KEY" - aws configure set role_arn "$AWS_ROLE_ARN" - aws configure set source_profile helm_user - - echo "unset AWS_ACCESS_KEY_ID" >> $BASH_ENV - echo "unset AWS_SECRET_ACCESS_KEY" >> $BASH_ENV - - - run: - name: terraform init & apply - working_directory: *eks-terraform-path - command: | - terraform init - - terraform apply -var cluster_count=2 -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-transparent-proxy -enable-cni -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *eks-terraform-path - command: | - terraform destroy -var cluster_count=2 -auto-approve - when: always - - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "EKS CNI acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-openshift: - environment: - TEST_RESULTS: /tmp/test-results - parallelism: 1 - docker: - - image: *consul-helm-test-image - - steps: - - checkout - - build-cli - - run: - name: terraform init & apply - working_directory: *openshift-terraform-path - command: | - terraform init - az login --service-principal -u "$ARM_CLIENT_ID" -p "$ARM_CLIENT_SECRET" --tenant "$ARM_TENANT_ID" > /dev/null - terraform apply \ - -var cluster_count=2 \ - -var tags="{\"build_url\": \"$CIRCLE_BUILD_URL\"}" \ - -auto-approve - - primary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[0]) - secondary_kubeconfig=$(terraform output -json | jq -r .kubeconfigs.value[1]) - - echo "export primary_kubeconfig=$primary_kubeconfig" >> $BASH_ENV - echo "export secondary_kubeconfig=$secondary_kubeconfig" >> $BASH_ENV - - # Restore go module cache if there is one - - restore_cache: - keys: - - consul-helm-acceptance-modcache-v2-{{ checksum "acceptance/go.mod" }} - - - run: mkdir -p $TEST_RESULTS - - - run-acceptance-tests: - additional-flags: -kubeconfig="$primary_kubeconfig" -secondary-kubeconfig="$secondary_kubeconfig" -enable-openshift -enable-transparent-proxy -consul-image=hashicorppreview/consul-enterprise:1.13-dev - - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - - run: - name: terraform destroy - working_directory: *openshift-terraform-path - command: | - terraform destroy -auto-approve - when: always - - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "OpenShift acceptance tests failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-kind-1-23-consul-compat-nightly-1-11: - environment: - - TEST_RESULTS: /tmp/test-results - - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.11-dev" - - ENVOY_IMAGE: "envoyproxy/envoy:v1.20.2" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.48.0" - - HELM_CHART_VERSION: "0.48.0" - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.23.0" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - build-cli - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.11" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.11 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-kind-1-23-consul-compat-nightly-1-12: - environment: - - TEST_RESULTS: /tmp/test-results - - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.12-dev" - - ENVOY_IMAGE: "envoyproxy/envoy:v1.22.2" - - HELM_CHART_VERSION: "0.48.0" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.48.0" - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.23.0" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - build-cli - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.12" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.12 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" - - acceptance-kind-1-23-consul-compat-nightly-1-13: - environment: - - TEST_RESULTS: /tmp/test-results - - CONSUL_IMAGE: "docker.mirror.hashicorp.services/hashicorppreview/consul-enterprise:1.13-dev" - - ENVOY_IMAGE: "envoyproxy/envoy:v1.23.1" - - CONSUL_K8S_IMAGE: "docker.mirror.hashicorp.services/hashicorp/consul-k8s-control-plane:0.48.0" - - HELM_CHART_VERSION: "0.48.0" - machine: - image: ubuntu-2004:202010-01 - resource_class: xlarge - steps: - - checkout - - install-prereqs - - create-kind-clusters: - version: "v1.23.0" - - restore_cache: - keys: - - consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - - run: - name: go mod download - working_directory: *acceptance-mod-path - command: go mod download - - save_cache: - key: consul-helm-modcache-v2-{{ checksum "acceptance/go.mod" }} - paths: - - ~/.go_workspace/pkg/mod - - build-cli - - run: mkdir -p $TEST_RESULTS - - run-acceptance-tests: - additional-flags: -use-kind -kubecontext="kind-dc1" -secondary-kubecontext="kind-dc2" -enable-transparent-proxy -consul-k8s-image=$CONSUL_K8S_IMAGE -consul-image=$CONSUL_IMAGE -consul-version="1.13" -envoy-image=$ENVOY_IMAGE -helm-chart-version=$HELM_CHART_VERSION - - store_test_results: - path: /tmp/test-results - - store_artifacts: - path: /tmp/test-results - - slack/status: - channel: *slack-channel - fail_only: true - failure_message: "Acceptance tests against Kind with Kubernetes v1.23 with Consul 1.13 nightly failed. Check the logs at: ${CIRCLE_BUILD_URL}" - -######################## -# WORKFLOWS -######################## -# Workflows are a set of rules for defining a collection of jobs and their run order. -# This is where the pipeline tests and builds are constructed and triggers for running these tests -# are defined -workflows: - version: 2 - test-and-build: - jobs: - # Build this one control-plane binary so that acceptance and acceptance-tproxy will run - # The rest of these CircleCI jobs have been migrated to GitHub Actions. We need to wait until - # there is support for a larger pool of runners before the acceptance tests can - # be moved - # Run acceptance tests using the docker image built for the control plane for this particular - # branch - # This is run on every PR - - build-distro: - OS: "linux" - ARCH: "amd64 arm64" - name: build-distros-linux - - dev-upload-docker: - context: consul-ci - requires: - - build-distros-linux - - acceptance: - context: consul-ci - requires: - - dev-upload-docker - - acceptance-tproxy-cni: - context: consul-ci - requires: - - dev-upload-docker - - acceptance-tproxy: - context: consul-ci - requires: - - dev-upload-docker - - nightly-cleanup: - triggers: - - schedule: - cron: "0 12 * * *" # Run at 12 pm UTC (5 am PST) - filters: - branches: - only: - - main - jobs: - - cleanup-gcp-resources - - cleanup-azure-resources - - cleanup-eks-resources - - - nightly-acceptance-tests-release: - description: | - Tests which run on a release branch nightly. These exist separate from the main - acceptance tests so that they can run at their own cadence, but - contains the same sequence of jobs. - triggers: - - schedule: - cron: "0 0 * * *" # Run at 12 am UTC (5 pm PST) - filters: - branches: - only: - - release/0.49.x - jobs: - - build-distro: - OS: "linux" - ARCH: "amd64 arm64" - name: build-distros-linux - - dev-upload-docker: - requires: - - build-distros-linux - # Disable until we can use UBI images. - # - acceptance-openshift - - acceptance-gke-1-23: - requires: - - dev-upload-docker - - acceptance-gke-cni-1-23: - requires: - - acceptance-gke-1-23 - - acceptance-tproxy: - requires: - - dev-upload-docker - - nightly-acceptance-tests-main: - description: | - Tests which run on the main branch nightly. These exist separate from the release - acceptance tests so that they can run at their own cadence, but - contains the same sequence of jobs. - triggers: - - schedule: - cron: "0 0 * * *" # Run at 12 am UTC (5 pm PST) - filters: - branches: - only: - - main - jobs: - - build-distro: - OS: "linux" - ARCH: "amd64 arm64" - name: build-distros-linux - - dev-upload-docker: - requires: - - build-distros-linux - # Disable until we can use UBI images. - # - acceptance-openshift - - acceptance-gke-1-23: - requires: - - dev-upload-docker - - acceptance-gke-cni-1-23: - requires: - - acceptance-gke-1-23 - - acceptance-eks-1-21: - requires: - - dev-upload-docker - - acceptance-eks-cni-1-21: - requires: - - acceptance-eks-1-21 - - acceptance-aks-1-22: - requires: - - dev-upload-docker - - acceptance-aks-cni-1-22: - requires: - - acceptance-aks-1-22 - - acceptance-tproxy: - requires: - - dev-upload-docker - - nightly-kind-acceptance-tests-consul-compatability: - description: | - Acceptance tests which run nightly to verify the compatibility between - a consul-k8s binary and it's consul version pair. Tests will be conducted - for up to n-2 previous Consul-k8s releases. - triggers: - - schedule: - cron: "0 0 * * *" # Run at 12 am UTC (5 pm PST) - filters: - branches: - only: - - main - jobs: - - acceptance-kind-1-23-consul-compat-nightly-1-11 - - acceptance-kind-1-23-consul-compat-nightly-1-12 - - acceptance-kind-1-23-consul-compat-nightly-1-13 diff --git a/.github/workflows/jira-issues.yaml b/.github/workflows/jira-issues.yaml new file mode 100644 index 0000000000..dc743e9328 --- /dev/null +++ b/.github/workflows/jira-issues.yaml @@ -0,0 +1,85 @@ +# Copyright (c) HashiCorp, Inc. + +on: + issues: + types: [opened, closed, deleted, reopened] + issue_comment: + types: [created] + workflow_dispatch: + +name: Jira Community Issue Sync + +jobs: + sync: + runs-on: ubuntu-latest + name: Jira Community Issue sync + steps: + - name: Login + uses: atlassian/gajira-login@v3.0.0 + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Set ticket type + id: set-ticket-type + run: | + echo "TYPE=GH Issue" >> $GITHUB_OUTPUT + + - name: Set ticket labels + if: github.event.action == 'opened' + id: set-ticket-labels + run: | + LABELS="[" + if [[ "${{ contains(github.event.issue.labels.*.name, 'type/bug') }}" == "true" ]]; then LABELS+="\"type/bug\", "; fi + if [[ "${{ contains(github.event.issue.labels.*.name, 'type/enhancement') }}" == "true" ]]; then LABELS+="\"type/enhancement\", "; fi + if [[ ${#LABELS} != 1 ]]; then LABELS=${LABELS::-2}"]"; else LABELS+="]"; fi + echo "LABELS=${LABELS}" >> $GITHUB_OUTPUT + + - name: Create ticket if an issue is filed, or if PR not by a team member is opened + if: github.event.action == 'opened' + uses: tomhjp/gh-action-jira-create@v0.2.0 + with: + project: NET + issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" + summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.issue.number }}]: ${{ github.event.issue.title }}" + description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" + # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) + extraFields: '{ "customfield_10089": "${{ github.event.issue.html_url || github.event.pull_request.html_url }}", + "customfield_10371": { "value": "GitHub" }, + "customfield_10535": [{ "value": "Service Mesh" }], + "components": [{ "name": "${{ github.event.repository.name }}" }], + "labels": ${{ steps.set-ticket-labels.outputs.LABELS }} }' + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Search + if: github.event.action != 'opened' + id: search + uses: tomhjp/gh-action-jira-search@v0.2.1 + with: + # cf[10089] is Issue Link (use JIRA API to retrieve) + jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' + + - name: Sync comment + if: github.event.action == 'created' && steps.search.outputs.issue + uses: tomhjp/gh-action-jira-comment@v0.1.0 + with: + issue: ${{ steps.search.outputs.issue }} + comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" + + - name: Close ticket + if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue + uses: atlassian/gajira-transition@v2.0.1 + with: + issue: ${{ steps.search.outputs.issue }} + transition: "Closed" + + - name: Reopen ticket + if: github.event.action == 'reopened' && steps.search.outputs.issue + uses: atlassian/gajira-transition@v2.0.1 + with: + issue: ${{ steps.search.outputs.issue }} + transition: "To Do" diff --git a/.github/workflows/jira-pr.yaml b/.github/workflows/jira-pr.yaml new file mode 100644 index 0000000000..c07a92ee77 --- /dev/null +++ b/.github/workflows/jira-pr.yaml @@ -0,0 +1,99 @@ +# Copyright (c) HashiCorp, Inc. + +on: + pull_request_target: + types: [opened, closed, reopened] + workflow_dispatch: + +name: Jira Community PR Sync + +jobs: + sync: + runs-on: ubuntu-latest + name: Jira sync + steps: + - name: Login + uses: atlassian/gajira-login@v3.0.0 + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Set ticket type + id: set-ticket-type + run: | + echo "TYPE=GH Issue" >> $GITHUB_OUTPUT + + - name: Set ticket labels + if: github.event.action == 'opened' + id: set-ticket-labels + run: | + LABELS="[" + if [[ "${{ contains(github.event.issue.labels.*.name, 'type/bug') }}" == "true" ]]; then LABELS+="\"type/bug\", "; fi + if [[ "${{ contains(github.event.issue.labels.*.name, 'type/enhancement') }}" == "true" ]]; then LABELS+="\"type/enhancement\", "; fi + if [[ ${#LABELS} != 1 ]]; then LABELS=${LABELS::-2}"]"; else LABELS+="]"; fi + echo "LABELS=${LABELS}" >> $GITHUB_OUTPUT + + - name: Check if team member + if: github.event.action == 'opened' + id: is-team-member + run: | + TEAM=consul + ROLE="$(hub api orgs/hashicorp/teams/${TEAM}/memberships/${{ github.actor }} | jq -r '.role | select(.!=null)')" + if [[ -n ${ROLE} ]]; then + echo "Actor ${{ github.actor }} is a ${TEAM} team member" + echo "MESSAGE=true" >> $GITHUB_OUTPUT + else + echo "Actor ${{ github.actor }} is NOT a ${TEAM} team member" + echo "MESSAGE=false" >> $GITHUB_OUTPUT + fi + env: + GITHUB_TOKEN: ${{ secrets.JIRA_SYNC_GITHUB_TOKEN }} + + - name: Create ticket if an issue is filed, or if PR not by a team member is opened + if: ( github.event.action == 'opened' && steps.is-team-member.outputs.MESSAGE == 'false' ) + uses: tomhjp/gh-action-jira-create@v0.2.0 + with: + project: NET + issuetype: "${{ steps.set-ticket-type.outputs.TYPE }}" + summary: "${{ github.event.repository.name }} [${{ steps.set-ticket-type.outputs.TYPE }} #${{ github.event.pull_request.number }}]: ${{ github.event.pull_request.title }}" + description: "${{ github.event.issue.body || github.event.pull_request.body }}\n\n_Created in GitHub by ${{ github.actor }}._" + # customfield_10089 is "Issue Link", customfield_10371 is "Source" (use JIRA API to retrieve) + extraFields: '{ "customfield_10089": "${{ github.event.pull_request.html_url }}", + "customfield_10371": { "value": "GitHub" }, + "customfield_10535": [{ "value": "Service Mesh" }], + "components": [{ "name": "${{ github.event.repository.name }}" }], + "labels": ${{ steps.set-ticket-labels.outputs.LABELS }} }' + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + + - name: Search + if: github.event.action != 'opened' + id: search + uses: tomhjp/gh-action-jira-search@v0.2.1 + with: + # cf[10089] is Issue Link (use JIRA API to retrieve) + jql: 'issuetype = "${{ steps.set-ticket-type.outputs.TYPE }}" and cf[10089] = "${{ github.event.issue.html_url || github.event.pull_request.html_url }}"' + + - name: Sync comment + if: github.event.action == 'created' && steps.search.outputs.issue + uses: tomhjp/gh-action-jira-comment@v0.1.0 + with: + issue: ${{ steps.search.outputs.issue }} + comment: "${{ github.actor }} ${{ github.event.review.state || 'commented' }}:\n\n${{ github.event.comment.body || github.event.review.body }}\n\n${{ github.event.comment.html_url || github.event.review.html_url }}" + + - name: Close ticket + if: ( github.event.action == 'closed' || github.event.action == 'deleted' ) && steps.search.outputs.issue + uses: atlassian/gajira-transition@v2.0.1 + with: + issue: ${{ steps.search.outputs.issue }} + transition: "Closed" + + - name: Reopen ticket + if: github.event.action == 'reopened' && steps.search.outputs.issue + uses: atlassian/gajira-transition@v2.0.1 + with: + issue: ${{ steps.search.outputs.issue }} + transition: "To Do" diff --git a/.github/workflows/merge.yml b/.github/workflows/merge.yml new file mode 100644 index 0000000000..be1b392f4a --- /dev/null +++ b/.github/workflows/merge.yml @@ -0,0 +1,31 @@ +# Dispatch to the consul-k8s-workflows when a PR is created and on merges to main/release* +name: merge +on: + push: + # Sequence of patterns matched against refs/heads + branches: + # Push events on main branch + - main + # Push events to branches matching refs/heads/release/** + - "release/**" + +# these should be the only settings that you will ever need to change +env: + CONSUL_IMAGE: hashicorppreview/consul-enterprise:1.16-dev # Consul's enterprise version to use in tests. We use this consul image on release branches too + BRANCH: ${{ github.head_ref || github.ref_name }} + CONTEXT: "merge" + SHA: ${{ github.event.pull_request.head.sha || github.sha }} + +jobs: + test: + name: test + runs-on: ubuntu-latest + steps: + - uses: benc-uk/workflow-dispatch@v1.2.2 + name: test + with: + workflow: test.yml + repo: hashicorp/consul-k8s-workflows + ref: main + token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} + inputs: '{ "context":"${{ env.CONTEXT }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ env.SHA }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}", "consul-image":"${{ env.CONSUL_IMAGE }}" }' diff --git a/.github/workflows/nightly-acceptance.yml b/.github/workflows/nightly-acceptance.yml new file mode 100644 index 0000000000..b8b7f50798 --- /dev/null +++ b/.github/workflows/nightly-acceptance.yml @@ -0,0 +1,27 @@ +# Dispatch to the consul-k8s-workflows with a nightly cron +name: nightly-acceptance +on: + schedule: + # * is a special character in YAML so you have to quote this string + # Run nightly at 12AM UTC/8PM EST/5PM PST + - cron: '0 0 * * *' + +# these should be the only settings that you will ever need to change +env: + CONSUL_IMAGE: hashicorppreview/consul-enterprise:1.16-dev # Consul's enterprise version to use in tests + BRANCH: ${{ github.ref_name }} + CONTEXT: "nightly" + +jobs: + cloud: + name: cloud + runs-on: ubuntu-latest + steps: + - uses: benc-uk/workflow-dispatch@v1.2.2 + name: cloud + with: + workflow: cloud.yml + repo: hashicorp/consul-k8s-workflows + ref: main + token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} + inputs: '{ "context":"${{ env.CONTEXT }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ github.sha }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}", "consul-image":"${{ env.CONSUL_IMAGE }}" }' diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 0000000000..c567310f2b --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,26 @@ +# Dispatch to the consul-k8s-workflows when a PR is created and on merges to main/release* +name: pr +on: + pull_request: + +# these should be the only settings that you will ever need to change +env: + CONSUL_IMAGE: hashicorppreview/consul-enterprise:1.13-dev # Consul's enterprise version to use in tests + BRANCH: ${{ github.head_ref || github.ref_name }} + CONTEXT: "pr" + SHA: ${{ github.event.pull_request.head.sha || github.sha }} + GOLANGCI_LINT_VERSION: "v1.46.2" + +jobs: + test: + name: test + runs-on: ubuntu-latest + steps: + - uses: benc-uk/workflow-dispatch@v1.2.2 + name: test + with: + workflow: test.yml + repo: hashicorp/consul-k8s-workflows + ref: main + token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} + inputs: '{ "context":"${{ env.CONTEXT }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ env.SHA }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}", "consul-image":"${{ env.CONSUL_IMAGE }}", "golangci-lint-version":"${{ env.GOLANGCI_LINT_VERSION }}" }' diff --git a/.github/workflows/reusable-acceptance.yml b/.github/workflows/reusable-acceptance.yml deleted file mode 100644 index 56389bb346..0000000000 --- a/.github/workflows/reusable-acceptance.yml +++ /dev/null @@ -1,128 +0,0 @@ -name: reusable-acceptance - -on: - workflow_call: - inputs: - name: - required: true - type: string - additional-flags: - required: false - type: string - default: "" - consul-k8s-image: - required: false - type: string - default: docker.mirror.hashicorp.services/hashicorpdev/consul-k8s-control-plane:latest - directory: - required: true - type: string - go-version: - required: true - type: string - gotestsum-version: - required: true - type: string - kind-version: - required: false - type: string - default: "v1.22.4" - secrets: - CONSUL_ENT_LICENSE: - required: true - -# Environment variables can only be used at the step level -env: - TEST_RESULTS: /tmp/test-results # path to where test results are saved - CONSUL_ENT_LICENSE: ${{ secrets.CONSUL_ENT_LICENSE }} - -jobs: - job: - runs-on: ubuntu-latest - strategy: - matrix: - include: # I am really sorry for this but I could not find a way to automatically split our tests into several runners. For now, split manually. - - {runner: "0", test-packages: "basic connect consul-dns"} - - {runner: "1", test-packages: "controller example ingress-gateway"} - - {runner: "2", test-packages: "mesh-gateway metrics"} - - {runner: "3", test-packages: "partitions sync terminating-gateway"} - - {runner: "4", test-packages: "vault"} - - fail-fast: true - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ inputs.go-version }} - - - name: Setup go mod cache - uses: actions/cache@v2 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Install gotestsum - run: | - wget https://github.com/gotestyourself/gotestsum/releases/download/v"${{ inputs.gotestsum-version }}"/gotestsum_"${{ inputs.gotestsum-version }}"_linux_amd64.tar.gz - sudo tar -C /usr/local/bin -xzf gotestsum_"${{ inputs.gotestsum-version }}"_linux_amd64.tar.gz - rm gotestsum_"${{ inputs.gotestsum-version }}"_linux_amd64.tar.gz - - - run: mkdir -p ${{ env.TEST_RESULTS }} - - - name: go mod download - working-directory: ${{ inputs.directory }} - run: go mod download - - - name: Create kind clusters - run: | - kind create cluster --name dc1 --image kindest/node:${{ inputs.kind-version }} - kind create cluster --name dc2 --image kindest/node:${{ inputs.kind-version }} - - # We have to run the tests for each package separately so that we can - # exit early if any test fails (-failfast only works within a single - # package). - - name: Run acceptance tests ${{ matrix.runner }} - working-directory: ${{ inputs.directory }} - if: github.repository_owner == 'hashicorp' # This prevents running on forks - run: | - exit_code=0 - echo "Running packages: ${{ matrix.test-packages }}" - for pkg in $(echo ${{ matrix.test-packages }}) - do - fullpkg="github.com/hashicorp/consul-k8s/${{ inputs.directory }}/${pkg}" - echo "Testing package: ${fullpkg}" - if ! gotestsum --jsonfile=jsonfile-${pkg////-} -- ${fullpkg} -p 1 -timeout 2h -failfast \ - ${{ inputs.additional-flags }} \ - -enable-enterprise \ - -enable-multi-cluster \ - -debug-directory=${{ env.TEST_RESULTS }}/debug \ - -consul-k8s-image=${{ inputs.consul-k8s-image }} - then - echo "Tests in ${pkg} failed, aborting early" - exit_code=1 - break - fi - done - gotestsum --raw-command --junitfile "${{ env.TEST_RESULTS }}/gotestsum-report.xml" -- cat jsonfile* - exit $exit_code - - - name: Upload tests - if: always() - uses: actions/upload-artifact@v2 - with: - name: ${{ inputs.name }}-${{ matrix.test-packages }}-gotestsum-report.xml - path: ${{ env.TEST_RESULTS }}/gotestsum-report.xml - - - name: Upload debug (on failure) - if: failure() - uses: actions/upload-artifact@v2 - with: - name: ${{ inputs.name }}-${{ matrix.test-packages }}-debug-info - path: ${{ env.TEST_RESULTS }}/debug diff --git a/.github/workflows/reusable-golangci-lint.yml b/.github/workflows/reusable-golangci-lint.yml deleted file mode 100644 index c8c3793b03..0000000000 --- a/.github/workflows/reusable-golangci-lint.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: golangci-lint - -on: - workflow_call: - inputs: - directory: - required: true - type: string - go-version: - required: true - type: string - args: - required: false - type: string - -jobs: - job: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ inputs.go-version }} - - - name: golangci-lint-${{inputs.directory}} - uses: golangci/golangci-lint-action@v3.2.0 - with: - version: v1.46.2 - working-directory: ${{inputs.directory}} - args: ${{inputs.args}} diff --git a/.github/workflows/reusable-unit.yml b/.github/workflows/reusable-unit.yml deleted file mode 100644 index 9e563e0203..0000000000 --- a/.github/workflows/reusable-unit.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: reusable-unit - -on: - workflow_call: - inputs: - directory: - required: true - type: string - go-version: - required: true - type: string - -# Environment variables can only be used at the step level -env: - TEST_RESULTS: /tmp/test-results # path to where test results are saved - GOTESTSUM_VERSION: 1.8.1 - -jobs: - job: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{inputs.go-version}} - - - name: Setup go mod cache - uses: actions/cache@v2 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Install gotestsum - run: | - wget https://github.com/gotestyourself/gotestsum/releases/download/v${{env.GOTESTSUM_VERSION}}/gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - sudo tar -C /usr/local/bin -xzf gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - rm gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - - - run: mkdir -p ${{env.TEST_RESULTS}} - - - name: go mod download - working-directory: ${{inputs.directory}} - run: go mod download - - - name: Run tests - working-directory: ${{inputs.directory}} - run: | - gotestsum --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml ./... -- -p 4 - diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 422e0654f5..0000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,342 +0,0 @@ -name: test -on: - push: - -env: - TEST_RESULTS: /tmp/test-results # path to where test results are saved - CONSUL_VERSION: 1.13.3 # Consul's OSS version to use in tests - CONSUL_ENT_VERSION: 1.13.3+ent # Consul's enterprise version to use in tests - GOTESTSUM_VERSION: 1.8.1 # You cannot use environment variables with workflows. The gotestsum version is hardcoded in the reusable workflows too. - -jobs: - terraform-fmt-check: - name: "Terraform format check" - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Setup Terraform - uses: hashicorp/setup-terraform@v2 - with: - terraform_version: TERRAFORM_VERSION - terraform_wrapper: false - - name: Run Terraform checks - run: | - make terraform-fmt-check TERRAFORM_DIR="${{ github.workspace }}" - - get-go-version: - name: "Determine Go toolchain version" - runs-on: ubuntu-latest - outputs: - go-version: ${{ steps.get-go-version.outputs.go-version }} - steps: - - uses: actions/checkout@v2 - - name: Determine Go version - id: get-go-version - # We use .go-version as our source of truth for current Go - # version, because "goenv" can react to it automatically. - run: | - echo "Building with Go $(cat .go-version)" - echo "::set-output name=go-version::$(cat .go-version)" - - validate-helm-gen: - needs: - - get-go-version - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ needs.get-go-version.outputs.go-version }} - - - name: Setup go mod cache - uses: actions/cache@v2 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Validate helm gen - working-directory: hack/helm-reference-gen - run: | - go run ./... -validate - - golangci-lint-helm-gen: - needs: - - get-go-version - uses: ./.github/workflows/reusable-golangci-lint.yml - with: - directory: hack/helm-reference-gen - go-version: ${{ needs.get-go-version.outputs.go-version }} - #TODO: This is a workaround in order to get pipelines working. godot and staticcheck fail for helm-reference-gen - args: "--no-config --disable-all --enable gofmt,govet" - - unit-helm-gen: - needs: [get-go-version, golangci-lint-helm-gen, validate-helm-gen] - uses: ./.github/workflows/reusable-unit.yml - with: - directory: hack/helm-reference-gen - go-version: ${{ needs.get-go-version.outputs.go-version }} - - unit-test-helm-templates: - needs: - - unit-helm-gen - runs-on: ubuntu-latest - container: - image: docker.mirror.hashicorp.services/hashicorpdev/consul-helm-test:0.12.0 - options: --user 1001 - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Run Unit Tests - working-directory: charts/consul - run: bats --jobs 4 ./test/unit - - lint-control-plane: - needs: - - get-go-version - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ needs.get-go-version.outputs.go-version }} - - - run: go install github.com/hashicorp/lint-consul-retry@master && lint-consul-retry - - - name: Run lint - working-directory: control-plane - run: go run hack/lint-api-new-client/main.go - - golangci-lint-control-plane: - needs: - - get-go-version - uses: ./.github/workflows/reusable-golangci-lint.yml - with: - directory: control-plane - go-version: ${{ needs.get-go-version.outputs.go-version }} - - test-control-plane: - needs: [get-go-version, lint-control-plane, golangci-lint-control-plane] - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ needs.get-go-version.outputs.go-version }} - - - name: Setup go mod cache - uses: actions/cache@v2 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Install gotestsum - run: | - wget https://github.com/gotestyourself/gotestsum/releases/download/v${{env.GOTESTSUM_VERSION}}/gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - sudo tar -C /usr/local/bin -xzf gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - rm gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - - - run: mkdir -p ${{env.TEST_RESULTS}} - - run: echo "$HOME/bin" >> $GITHUB_PATH - - - name: Download consul - working-directory: control-plane - run: | - mkdir -p $HOME/bin - wget https://releases.hashicorp.com/consul/${{env.CONSUL_VERSION}}/consul_${{env.CONSUL_VERSION}}_linux_amd64.zip && \ - unzip consul_${{env.CONSUL_VERSION}}_linux_amd64.zip -d $HOME/bin && \ - rm consul_${{env.CONSUL_VERSION}}_linux_amd64.zip - chmod +x $HOME/bin/consul - - - name: Run go tests - working-directory: control-plane - run: | - PACKAGE_NAMES=$(go list ./...) - gotestsum --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- -p 4 $PACKAGE_NAMES - - test-enterprise-control-plane: - if: github.repository_owner == 'hashicorp' # Do not run on forks as this requires secrets - needs: [get-go-version, lint-control-plane, golangci-lint-control-plane] - runs-on: ubuntu-latest - env: - CONSUL_LICENSE: ${{secrets.CONSUL_LICENSE}} - steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ needs.get-go-version.outputs.go-version }} - - - name: Setup go mod cache - uses: actions/cache@v2 - with: - path: | - ~/.cache/go-build - ~/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - - - name: Install gotestsum - run: | - wget https://github.com/gotestyourself/gotestsum/releases/download/v${{env.GOTESTSUM_VERSION}}/gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - sudo tar -C /usr/local/bin -xzf gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - rm gotestsum_${{env.GOTESTSUM_VERSION}}_linux_amd64.tar.gz - - - run: mkdir -p ${{env.TEST_RESULTS}} - - run: echo "$HOME/bin" >> $GITHUB_PATH - - - name: Download consul - working-directory: control-plane - run: | - mkdir -p $HOME/bin - wget https://releases.hashicorp.com/consul/${{env.CONSUL_ENT_VERSION}}/consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip && \ - unzip consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip -d $HOME/bin && \ - rm consul_${{env.CONSUL_ENT_VERSION}}_linux_amd64.zip - chmod +x $HOME/bin/consul - - - name: Run go tests - working-directory: control-plane - run: | - PACKAGE_NAMES=$(go list ./...) - gotestsum --junitfile ${{env.TEST_RESULTS}}/gotestsum-report.xml -- -tags=enterprise -p 4 $PACKAGE_NAMES - - build-distros: - needs: [get-go-version, test-control-plane, test-enterprise-control-plane] - runs-on: ubuntu-latest - strategy: - matrix: - include: - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "386"} - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "amd64"} - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm"} - - {go: "${{ needs.get-go-version.outputs.go-version }}", goos: "linux", goarch: "arm64"} - fail-fast: true - - name: Go ${{ matrix.go }} ${{ matrix.goos }} ${{ matrix.goarch }} build - steps: - - uses: actions/checkout@v2 - - - name: Setup go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go }} - - - name: Build - working-directory: control-plane - env: - GOOS: ${{ matrix.goos }} - GOARCH: ${{ matrix.goarch }} - CGO_ENABLED: 0 - run: | - XC_OS=${{ matrix.goos }} XC_ARCH=${{ matrix.goarch }} ./build-support/scripts/build-local.sh - zip -r -j consul-k8s_${{ matrix.goos }}_${{ matrix.goarch }}.zip bin - - - uses: actions/upload-artifact@v2 - with: - name: consul-k8s_${{ matrix.goos }}_${{ matrix.goarch }}.zip - path: control-plane/consul-k8s_${{ matrix.goos }}_${{ matrix.goarch }}.zip - - golangci-lint-acceptance: - needs: - - get-go-version - uses: ./.github/workflows/reusable-golangci-lint.yml - with: - directory: acceptance - go-version: ${{ needs.get-go-version.outputs.go-version }} - - unit-acceptance-framework: - needs: [get-go-version, golangci-lint-acceptance] - uses: ./.github/workflows/reusable-unit.yml - with: - directory: acceptance/framework - go-version: ${{ needs.get-go-version.outputs.go-version }} - - golangci-lint-cli: - needs: - - get-go-version - uses: ./.github/workflows/reusable-golangci-lint.yml - with: - directory: cli - go-version: ${{ needs.get-go-version.outputs.go-version }} - - unit-cli: - needs: [get-go-version, golangci-lint-cli] - uses: ./.github/workflows/reusable-unit.yml - with: - directory: cli - go-version: ${{ needs.get-go-version.outputs.go-version }} - -# Disabling for now until we get faster VMs to run acceptance tests. Faster VMs for Github Actions are supposed -# to be available in the summer of 2022. For now, run the dev-upload docker and acceptance tests in CircleCI -# dev-upload-docker: -# if: github.repository_owner == 'hashicorp' # Do not run on forks as this requires secrets -# needs: build-distros -# runs-on: ubuntu-latest -# -# env: -# GITHUB_PULL_REQUEST: ${{github.event.pull_request.number}} -# DOCKER_USER: ${{secrets.DOCKER_USER}} -# DOCKER_PASS: ${{secrets.DOCKER_PASS}} -# steps: -# - uses: actions/checkout@v2 -# -# - run: mkdir -p control-plane/pkg/bin/linux_amd64 -# -# - uses: actions/download-artifact@v3 -# with: -# name: consul-k8s_linux_amd64.zip -# path: control-plane -# -# - name: Docker build -# working-directory: control-plane -# run: | -# unzip consul-k8s_linux_amd64.zip -d ./pkg/bin/linux_amd64 -# make ci.dev-docker-github -# -# acceptance-tproxy: -# needs: [get-go-version, unit-cli, dev-upload-docker, unit-acceptance-framework, unit-test-helm-templates] -# needs: dev-upload-docker -# uses: ./.github/workflows/reusable-acceptance.yml -# with: -# name: acceptance-tproxy -# directory: acceptance/tests -# go-version: ${{ needs.get-go-version.outputs.go-version }} -# additional-flags: "-use-kind -kubecontext=kind-dc1 -secondary-kubecontext=kind-dc2 -enable-transparent-proxy" -# gotestsum-version: 1.6.4 -# secrets: -# CONSUL_ENT_LICENSE: ${{ secrets.CONSUL_ENT_LICENSE }} -# -# acceptance: -# #needs: [get-go-version, unit-cli, dev-upload-docker, unit-acceptance-framework, unit-test-helm-templates] -# needs: dev-upload-docker -# uses: ./.github/workflows/reusable-acceptance.yml -# with: -# name: acceptance -# directory: acceptance/tests -# go-version: ${{ needs.get-go-version.outputs.go-version }} -# additional-flags: "-use-kind -kubecontext=kind-dc1 -secondary-kubecontext=kind-dc2" -# gotestsum-version: 1.6.4 -# secrets: -# CONSUL_ENT_LICENSE: ${{ secrets.CONSUL_ENT_LICENSE }} - - diff --git a/.github/workflows/weekly-acceptance-0-49-x.yml b/.github/workflows/weekly-acceptance-0-49-x.yml new file mode 100644 index 0000000000..7025bcb241 --- /dev/null +++ b/.github/workflows/weekly-acceptance-0-49-x.yml @@ -0,0 +1,29 @@ +# Dispatch to the consul-k8s-workflows with a weekly cron +# +# A separate file is needed for each release because the cron schedules are different for each release. +name: weekly-acceptance-0-49-x +on: + schedule: + # * is a special character in YAML so you have to quote this string + # Run weekly on Monday at 3AM UTC/11PM EST/8PM PST + - cron: '0 3 * * 1' + +# these should be the only settings that you will ever need to change +env: + CONSUL_IMAGE: hashicorppreview/consul-enterprise:1.13-dev # Consul's enterprise version to use in tests + BRANCH: "release/0.49.x" + CONTEXT: "weekly" + +jobs: + cloud: + name: cloud + runs-on: ubuntu-latest + steps: + - uses: benc-uk/workflow-dispatch@v1.2.2 + name: cloud + with: + workflow: cloud.yml + repo: hashicorp/consul-k8s-workflows + ref: main + token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} + inputs: '{ "context":"${{ env.CONTEXT }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ github.sha }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}", "consul-image":"${{ env.CONSUL_IMAGE }}" }' diff --git a/.github/workflows/weekly-acceptance-1-0-x.yml b/.github/workflows/weekly-acceptance-1-0-x.yml new file mode 100644 index 0000000000..4aa49594f3 --- /dev/null +++ b/.github/workflows/weekly-acceptance-1-0-x.yml @@ -0,0 +1,30 @@ +# Dispatch to the consul-k8s-workflows with a weekly cron +# +# A separate file is needed for each release because the cron schedules are different for each release. +name: weekly-acceptance-1-0-x +on: + schedule: + # * is a special character in YAML so you have to quote this string + # Run weekly on Tuesday at 3AM UTC/11PM EST/8PM PST + - cron: '0 3 * * 2' + + +# these should be the only settings that you will ever need to change +env: + CONSUL_IMAGE: hashicorppreview/consul-enterprise:1.14-dev # Consul's enterprise version to use in tests + BRANCH: "release/1.0.x" + CONTEXT: "weekly" + +jobs: + cloud: + name: cloud + runs-on: ubuntu-latest + steps: + - uses: benc-uk/workflow-dispatch@v1.2.2 + name: cloud + with: + workflow: cloud.yml + repo: hashicorp/consul-k8s-workflows + ref: main + token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} + inputs: '{ "context":"${{ env.CONTEXT }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ github.sha }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}", "consul-image":"${{ env.CONSUL_IMAGE }}" }' diff --git a/.github/workflows/weekly-acceptance-1-1-x.yml b/.github/workflows/weekly-acceptance-1-1-x.yml new file mode 100644 index 0000000000..1ffc6f8684 --- /dev/null +++ b/.github/workflows/weekly-acceptance-1-1-x.yml @@ -0,0 +1,30 @@ +# Dispatch to the consul-k8s-workflows with a weekly cron +# +# A separate file is needed for each release because the cron schedules are different for each release. +name: weekly-acceptance-1-1-x +on: + schedule: + # * is a special character in YAML so you have to quote this string + # Run weekly on Wednesday at 3AM UTC/11PM EST/8PM PST + - cron: '0 3 * * 3' + + +# these should be the only settings that you will ever need to change +env: + CONSUL_IMAGE: hashicorppreview/consul-enterprise:1.15-dev # Consul's enterprise version to use in tests + BRANCH: "release/1.1.x" + CONTEXT: "weekly" + +jobs: + cloud: + name: cloud + runs-on: ubuntu-latest + steps: + - uses: benc-uk/workflow-dispatch@v1.2.2 + name: cloud + with: + workflow: cloud.yml + repo: hashicorp/consul-k8s-workflows + ref: main + token: ${{ secrets.ELEVATED_GITHUB_TOKEN }} + inputs: '{ "context":"${{ env.CONTEXT }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ github.sha }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}", "consul-image":"${{ env.CONSUL_IMAGE }}" }' From 2891eebd03cd8aa346bbc60e6a1578eb28b5cb69 Mon Sep 17 00:00:00 2001 From: Dan Stough Date: Fri, 5 May 2023 18:01:32 -0400 Subject: [PATCH 224/235] Manual Backport of security: update Go version to 1.19.9 (#2108) (#2110) * security: update Go version to 1.19.9 * refactor: go fmt and go mod tidy --- .changelog/2110.txt | 12 +++++++++ .go-version | 2 +- acceptance/go.mod | 10 ++++---- acceptance/go.sum | 15 +++++++---- cli/go.mod | 8 +++--- cli/go.sum | 14 ++++++----- control-plane/cni/go.mod | 10 +++----- control-plane/cni/go.sum | 21 ++++++++-------- .../endpoints_controller_ent_test.go | 9 ++++--- .../connect-inject/redirect_traffic.go | 17 +++++++------ control-plane/go.mod | 9 ++++--- control-plane/go.sum | 18 +++++++------ .../subcommand/install-cni/cniconfig.go | 25 ++++++++++--------- 13 files changed, 97 insertions(+), 73 deletions(-) create mode 100644 .changelog/2110.txt diff --git a/.changelog/2110.txt b/.changelog/2110.txt new file mode 100644 index 0000000000..1c10ef62d9 --- /dev/null +++ b/.changelog/2110.txt @@ -0,0 +1,12 @@ +```release-note:security +Upgrade to use Go 1.19.9. +This resolves vulnerabilities [CVE-2023-24537](https://github.com/advisories/GHSA-9f7g-gqwh-jpf5)(`go/scanner`), +[CVE-2023-24538](https://github.com/advisories/GHSA-v4m2-x4rp-hv22)(`html/template`), +[CVE-2023-24534](https://github.com/advisories/GHSA-8v5j-pwr7-w5f8)(`net/textproto`) and +[CVE-2023-24536](https://github.com/advisories/GHSA-9f7g-gqwh-jpf5)(`mime/multipart`). +Also, `golang.org/x/net` has been updated to v0.7.0 to resolve CVEs [CVE-2022-41721 +](https://github.com/advisories/GHSA-fxg5-wq6x-vr4w +), [CVE-2022-27664](https://github.com/advisories/GHSA-69cg-p879-7622) and [CVE-2022-41723 +](https://github.com/advisories/GHSA-vvpx-j8f3-3w6h +.) +``` \ No newline at end of file diff --git a/.go-version b/.go-version index 2a4feaf54c..91c48c058d 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.19.6 +1.19.9 diff --git a/acceptance/go.mod b/acceptance/go.mod index 5c8893cac5..8990fb45bc 100644 --- a/acceptance/go.mod +++ b/acceptance/go.mod @@ -82,12 +82,12 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/urfave/cli v1.22.2 // indirect go.uber.org/atomic v1.7.0 // indirect - golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 // indirect - golang.org/x/net v0.0.0-20211216030914-fe4d6282115f // indirect + golang.org/x/crypto v0.1.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect - golang.org/x/text v0.3.6 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect diff --git a/acceptance/go.sum b/acceptance/go.sum index 8bb13efef3..b9401d6e65 100644 --- a/acceptance/go.sum +++ b/acceptance/go.sum @@ -656,8 +656,9 @@ golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -730,8 +731,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211216030914-fe4d6282115f h1:hEYJvxw1lSnWIl8X9ofsYMklzaDs90JI2az5YMd4fPM= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -802,12 +804,14 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -815,8 +819,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/cli/go.mod b/cli/go.mod index 3151328406..f4a9dda92f 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -131,12 +131,12 @@ require ( github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect go.starlark.net v0.0.0-20200707032745-474f21a9602d // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect - golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect diff --git a/cli/go.sum b/cli/go.sum index 531cb6f202..0e0445aad9 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -796,8 +796,8 @@ golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -906,11 +906,12 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -919,8 +920,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/control-plane/cni/go.mod b/control-plane/cni/go.mod index 7b97f5d07f..c7c676519c 100644 --- a/control-plane/cni/go.mod +++ b/control-plane/cni/go.mod @@ -1,7 +1,6 @@ module github.com/hashicorp/consul-k8s/control-plane/cni require ( - github.com/cenkalti/backoff v2.1.1+incompatible github.com/containernetworking/cni v1.1.1 github.com/containernetworking/plugins v1.1.1 github.com/hashicorp/consul/sdk v0.9.0 @@ -31,12 +30,11 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.1.0 // indirect - golang.org/x/net v0.0.0-20211209124913-491a49abca63 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect - golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect - golang.org/x/text v0.3.7 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.26.0 // indirect diff --git a/control-plane/cni/go.sum b/control-plane/cni/go.sum index 03309565a1..b7d471c97f 100644 --- a/control-plane/cni/go.sum +++ b/control-plane/cni/go.sum @@ -34,8 +34,6 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0 github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= -github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -64,6 +62,7 @@ github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.3+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -184,6 +183,7 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -211,13 +211,11 @@ github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzu github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= -github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -288,8 +286,8 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211209124913-491a49abca63 h1:iocB37TsdFuN6IBRZ+ry36wrkoV51/tl5vOWqkcPGvY= -golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -336,20 +334,22 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -458,6 +458,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/control-plane/connect-inject/endpoints_controller_ent_test.go b/control-plane/connect-inject/endpoints_controller_ent_test.go index 5859bd9206..8ae83656b9 100644 --- a/control-plane/connect-inject/endpoints_controller_ent_test.go +++ b/control-plane/connect-inject/endpoints_controller_ent_test.go @@ -318,12 +318,13 @@ func TestReconcileCreateEndpointWithNamespaces(t *testing.T) { // Tests updating an Endpoints object when Consul namespaces are enabled. // - Tests updates via the register codepath: -// - When an address in an Endpoint is updated, that the corresponding service instance in Consul is updated in the correct Consul namespace. -// - When an address is added to an Endpoint, an additional service instance in Consul is registered in the correct Consul namespace. +// - When an address in an Endpoint is updated, that the corresponding service instance in Consul is updated in the correct Consul namespace. +// - When an address is added to an Endpoint, an additional service instance in Consul is registered in the correct Consul namespace. // - Tests updates via the deregister codepath: -// - When an address is removed from an Endpoint, the corresponding service instance in Consul is deregistered. -// - When an address is removed from an Endpoint *and there are no addresses left in the Endpoint*, the +// - When an address is removed from an Endpoint, the corresponding service instance in Consul is deregistered. +// - When an address is removed from an Endpoint *and there are no addresses left in the Endpoint*, the // corresponding service instance in Consul is deregistered. +// // For the register and deregister codepath, this also tests that they work when the Consul service name is different // from the K8s service name. // This test covers EndpointsController.deregisterServiceOnAllAgents when services should be selectively deregistered diff --git a/control-plane/connect-inject/redirect_traffic.go b/control-plane/connect-inject/redirect_traffic.go index 71aebf54e7..a6f3166603 100644 --- a/control-plane/connect-inject/redirect_traffic.go +++ b/control-plane/connect-inject/redirect_traffic.go @@ -12,14 +12,15 @@ import ( // addRedirectTrafficConfigAnnotation creates an iptables.Config based on proxy configuration. // iptables.Config: -// ConsulDNSIP: an environment variable named RESOURCE_PREFIX_DNS_SERVICE_HOST where RESOURCE_PREFIX is the consul.fullname in helm. -// ProxyUserID: a constant set in Annotations -// ProxyInboundPort: the service port or bind port -// ProxyOutboundPort: default transparent proxy outbound port or transparent proxy outbound listener port -// ExcludeInboundPorts: prometheus, envoy stats, expose paths, checks and excluded pod annotations -// ExcludeOutboundPorts: pod annotations -// ExcludeOutboundCIDRs: pod annotations -// ExcludeUIDs: pod annotations +// +// ConsulDNSIP: an environment variable named RESOURCE_PREFIX_DNS_SERVICE_HOST where RESOURCE_PREFIX is the consul.fullname in helm. +// ProxyUserID: a constant set in Annotations +// ProxyInboundPort: the service port or bind port +// ProxyOutboundPort: default transparent proxy outbound port or transparent proxy outbound listener port +// ExcludeInboundPorts: prometheus, envoy stats, expose paths, checks and excluded pod annotations +// ExcludeOutboundPorts: pod annotations +// ExcludeOutboundCIDRs: pod annotations +// ExcludeUIDs: pod annotations func (w *MeshWebhook) addRedirectTrafficConfigAnnotation(pod *corev1.Pod, ns corev1.Namespace) error { cfg := iptables.Config{ ProxyUserID: strconv.Itoa(envoyUserAndGroupID), diff --git a/control-plane/go.mod b/control-plane/go.mod index e72be74610..021d1612bc 100644 --- a/control-plane/go.mod +++ b/control-plane/go.mod @@ -22,7 +22,7 @@ require ( github.com/mitchellh/mapstructure v1.4.1 github.com/stretchr/testify v1.7.2 go.uber.org/zap v1.19.0 - golang.org/x/text v0.3.7 + golang.org/x/text v0.7.0 golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 gomodules.xyz/jsonpatch/v2 v2.2.0 k8s.io/api v0.22.2 @@ -107,11 +107,12 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 // indirect - golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/term v0.5.0 // indirect + golang.org/x/tools v0.2.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/api v0.43.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/control-plane/go.sum b/control-plane/go.sum index 54a0604111..a35e1b61fb 100644 --- a/control-plane/go.sum +++ b/control-plane/go.sum @@ -795,8 +795,8 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= -golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -898,13 +898,14 @@ golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10 h1:WIoqL4EROvwiPdUtaip4VcDdpZ4kha7wBWZrbVKCIZg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= -golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -914,8 +915,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -981,8 +982,9 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/control-plane/subcommand/install-cni/cniconfig.go b/control-plane/subcommand/install-cni/cniconfig.go index e4d2078ad7..922d7283dd 100644 --- a/control-plane/subcommand/install-cni/cniconfig.go +++ b/control-plane/subcommand/install-cni/cniconfig.go @@ -111,18 +111,19 @@ func confListFileFromConfFile(cfgFile string) (string, error) { // The format of the main cni config file is unstructured json consisting of a header and list of plugins // -// { -// "cniVersion": "0.3.1", -// "name": "kindnet", -// "plugins": [ -// { -// -// }, -// { -// -// } -// ] -// } +// { +// "cniVersion": "0.3.1", +// "name": "kindnet", +// "plugins": [ +// { +// +// }, +// { +// +// } +// ] +// } +// // appendCNIConfig appends the consul-cni configuration to the main configuration file. func appendCNIConfig(consulCfg *config.CNIConfig, cfgFile string) error { // Read the config file and convert it to a map. From 499d4fccc351e0a5ce5ff7b6e98f91245f74d3b2 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Mon, 8 May 2023 10:20:58 -0400 Subject: [PATCH 225/235] backport of commit 620a80b79e3ac52dd3d44437940e24394e4d776b (#2112) Co-authored-by: DanStough --- .github/workflows/changelog-checker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index ae2e88170b..5c60e9a38a 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -34,7 +34,7 @@ jobs: changelog_file_path=".changelog/[_0-9]*.txt" fi - changelog_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/main")" | egrep ${changelog_file_path}) + changelog_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/${{ github.event.pull_request.base.ref }}")" | egrep -e "${changelog_file_path}")) # If we do not find a file in .changelog/, we fail the check if [ -z "$changelog_files" ]; then From 7554e65f82d9b01d4966a36cffff2cd6fb7e23bc Mon Sep 17 00:00:00 2001 From: Dan Stough Date: Mon, 8 May 2023 11:27:08 -0400 Subject: [PATCH 226/235] chore(ci): fix backport assistant not finding new branches (#2116) --- .github/workflows/backport.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index c1548332e0..48883e24fa 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -11,10 +11,10 @@ jobs: backport: if: github.event.pull_request.merged runs-on: ubuntu-latest - container: hashicorpdev/backport-assistant:0.2.5 + container: hashicorpdev/backport-assistant:0.3.3 steps: - name: Run Backport Assistant - run: backport-assistant backport -automerge + run: backport-assistant backport -merge-method=squash -gh-automerge env: BACKPORT_LABEL_REGEXP: "backport/(?P\\d+\\.\\d+\\.x)" BACKPORT_TARGET_TEMPLATE: "release/{{.target}}" From d1dc5788b9f6956a6c1d8e5c9cfc739c55d6d615 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Fri, 12 May 2023 17:12:33 -0400 Subject: [PATCH 227/235] backport of commit ee35a303a76a6b971975e8517624101a3a8d71cd (#2130) Co-authored-by: DanStough --- .github/workflows/changelog-checker.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/changelog-checker.yml b/.github/workflows/changelog-checker.yml index 5c60e9a38a..d40bdfbd6a 100644 --- a/.github/workflows/changelog-checker.yml +++ b/.github/workflows/changelog-checker.yml @@ -34,7 +34,7 @@ jobs: changelog_file_path=".changelog/[_0-9]*.txt" fi - changelog_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/${{ github.event.pull_request.base.ref }}")" | egrep -e "${changelog_file_path}")) + changelog_files=$(git --no-pager diff --name-only HEAD "$(git merge-base HEAD "origin/${{ github.event.pull_request.base.ref }}")" | egrep -e "${changelog_file_path}") # If we do not find a file in .changelog/, we fail the check if [ -z "$changelog_files" ]; then From d6c7157d6ae7c960ec50d89707e457d31bbdd642 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Wed, 17 May 2023 18:43:41 -0400 Subject: [PATCH 228/235] backport of commit 3fdcf9695bd1c8e201aca22ee1a3a25778ffcd9d (#2147) Co-authored-by: Curt Bushko --- Makefile | 5 +++++ control-plane/build-support/scripts/consul-version.sh | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100755 control-plane/build-support/scripts/consul-version.sh diff --git a/Makefile b/Makefile index daee6b693b..ea94b303e9 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,5 @@ VERSION = $(shell ./control-plane/build-support/scripts/version.sh control-plane/version/version.go) +CONSUL_VERSION = $(shell ./control-plane/build-support/scripts/consul-version.sh charts/consul/values.yaml) # ===========> Helm Targets @@ -147,6 +148,10 @@ ci.aws-acceptance-test-cleanup: ## Deletes AWS resources left behind after faile version: @echo $(VERSION) +consul-version: + @echo $(CONSUL_VERSION) + + # ===========> Release Targets prepare-release: ## Sets the versions, updates changelog to prepare this repository to release diff --git a/control-plane/build-support/scripts/consul-version.sh b/control-plane/build-support/scripts/consul-version.sh new file mode 100755 index 0000000000..634b5db07d --- /dev/null +++ b/control-plane/build-support/scripts/consul-version.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 +FILE=$1 +VERSION=$(yq .global.image $FILE) + +# echo full string "hashicorp/consul:1.15.1" | remove first and last characters | cut everything before ':' +echo "${VERSION}" | sed 's/^.//;s/.$//' | cut -d ':' -f2- From fc450d8fc2e58bf4d26c850d83efeedfd1a57d46 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Wed, 17 May 2023 19:04:00 -0400 Subject: [PATCH 229/235] Prep release 0.49.6 (#2151) --- CHANGELOG.md | 19 +++++++++++++++++++ charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 6 +++--- cli/version/version.go | 2 +- control-plane/version/version.go | 2 +- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02375a2ae2..d395927c39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,22 @@ +## 0.49.6 (May 17, 2023) + +SECURITY: + +* Upgrade to use Go 1.19.9. +This resolves vulnerabilities [CVE-2023-24537](https://github.com/advisories/GHSA-9f7g-gqwh-jpf5)(`go/scanner`), +[CVE-2023-24538](https://github.com/advisories/GHSA-v4m2-x4rp-hv22)(`html/template`), +[CVE-2023-24534](https://github.com/advisories/GHSA-8v5j-pwr7-w5f8)(`net/textproto`) and +[CVE-2023-24536](https://github.com/advisories/GHSA-9f7g-gqwh-jpf5)(`mime/multipart`). +Also, `golang.org/x/net` has been updated to v0.7.0 to resolve CVEs [CVE-2022-41721 +](https://github.com/advisories/GHSA-fxg5-wq6x-vr4w +), [CVE-2022-27664](https://github.com/advisories/GHSA-69cg-p879-7622) and [CVE-2022-41723 +](https://github.com/advisories/GHSA-vvpx-j8f3-3w6h +.) [[GH-2110](https://github.com/hashicorp/consul-k8s/issues/2110)] + +IMPROVEMENTS: + +* helm: Set default `limits.cpu` resource setting to `null` for `consul-connect-inject-init` container to speed up registration times when onboarding services onto the mesh during the init container lifecycle. [[GH-2008](https://github.com/hashicorp/consul-k8s/issues/2008)] + ## 0.49.5 (March 9, 2023) SECURITY: diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index ccc02a74db..6b2e0aab98 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.6-dev +version: 0.49.6 appVersion: 1.13.7 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: true + artifacthub.io/prerelease: false artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.7 - name: consul-k8s-control-plane - image: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:0.49.6-dev + image: hashicorp/consul-k8s-control-plane:0.49.6 - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index c2b81c1ea1..8e3a4fac72 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -109,7 +109,7 @@ global: # image: "hashicorp/consul-enterprise:1.10.0-ent" # ``` # @default: hashicorp/consul: - image: "hashicorp/consul:1.13.7" + image: "hashicorp/consul:1.13.8" # Array of objects containing image pull secret names that will be applied to each service account. # This can be used to reference image pull secrets if using a custom consul or consul-k8s-control-plane Docker image. @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:0.49.6-dev + imageK8S: hashicorp/consul-k8s-control-plane:0.49.6 # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running @@ -648,7 +648,7 @@ global: # connect-injected sidecar proxies and mesh, terminating, and ingress gateways. # See https://www.consul.io/docs/connect/proxies/envoy for full compatibility matrix between Consul and Envoy. # @default: envoyproxy/envoy-alpine: - imageEnvoy: "envoyproxy/envoy:v1.23.1" + imageEnvoy: "envoyproxy/envoy:v1.23.8" # Configuration for running this Helm chart on the Red Hat OpenShift platform. # This Helm chart currently supports OpenShift v4.x+. diff --git a/cli/version/version.go b/cli/version/version.go index e63f0dde27..97aad5824f 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index e63f0dde27..97aad5824f 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -19,7 +19,7 @@ var ( // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "dev" + VersionPrerelease = "" ) // GetHumanVersion composes the parts of the version in a way that's suitable From cfa4465cf006c1105dc7ac0962025dd191693f65 Mon Sep 17 00:00:00 2001 From: Ashwin Venkatesh Date: Thu, 18 May 2023 13:07:58 -0400 Subject: [PATCH 230/235] set dev mode 0.49.7 (#2155) --- charts/consul/Chart.yaml | 6 +++--- charts/consul/values.yaml | 2 +- cli/version/version.go | 4 ++-- control-plane/version/version.go | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/charts/consul/Chart.yaml b/charts/consul/Chart.yaml index 6b2e0aab98..90a2dd4c2d 100644 --- a/charts/consul/Chart.yaml +++ b/charts/consul/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 name: consul -version: 0.49.6 +version: 0.49.7-dev appVersion: 1.13.7 kubeVersion: ">=1.21.0-0" description: Official HashiCorp Consul Chart @@ -10,12 +10,12 @@ sources: - https://github.com/hashicorp/consul - https://github.com/hashicorp/consul-k8s annotations: - artifacthub.io/prerelease: false + artifacthub.io/prerelease: true artifacthub.io/images: | - name: consul image: hashicorp/consul:1.13.7 - name: consul-k8s-control-plane - image: hashicorp/consul-k8s-control-plane:0.49.6 + image: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:0.49.7-dev - name: envoy image: envoyproxy/envoy:v1.23.1 artifacthub.io/license: MPL-2.0 diff --git a/charts/consul/values.yaml b/charts/consul/values.yaml index 8e3a4fac72..e7f4269df3 100644 --- a/charts/consul/values.yaml +++ b/charts/consul/values.yaml @@ -129,7 +129,7 @@ global: # image that is used for functionality such as catalog sync. # This can be overridden per component. # @default: hashicorp/consul-k8s-control-plane: - imageK8S: hashicorp/consul-k8s-control-plane:0.49.6 + imageK8S: docker.mirror.hashicorp.services/hashicorppreview/consul-k8s-control-plane:0.49.7-dev # The name of the datacenter that the agents should # register as. This can't be changed once the Consul cluster is up and running diff --git a/cli/version/version.go b/cli/version/version.go index 97aad5824f..13e26adad7 100644 --- a/cli/version/version.go +++ b/cli/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.6" + Version = "0.49.7" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable diff --git a/control-plane/version/version.go b/control-plane/version/version.go index 97aad5824f..13e26adad7 100644 --- a/control-plane/version/version.go +++ b/control-plane/version/version.go @@ -14,12 +14,12 @@ var ( // // Version must conform to the format expected by // github.com/hashicorp/go-version for tests to work. - Version = "0.49.6" + Version = "0.49.7" // A pre-release marker for the version. If this is "" (empty string) // then it means that it is a final release. Otherwise, this is a pre-release // such as "dev" (in development), "beta", "rc1", etc. - VersionPrerelease = "" + VersionPrerelease = "dev" ) // GetHumanVersion composes the parts of the version in a way that's suitable From b9f27852d3edd6f179ccdd14f314e5e495a614fd Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Fri, 26 May 2023 09:46:10 -0400 Subject: [PATCH 231/235] backport of commit 583d51ed58b8108f5b42ca1a4638ffbc5c0fb6d4 (#2186) Co-authored-by: Andrew Stucki --- acceptance/tests/api-gateway/example_test.go | 64 ++++++++++++++++++++ acceptance/tests/api-gateway/main_test.go | 37 +++++++++++ 2 files changed, 101 insertions(+) create mode 100644 acceptance/tests/api-gateway/example_test.go create mode 100644 acceptance/tests/api-gateway/main_test.go diff --git a/acceptance/tests/api-gateway/example_test.go b/acceptance/tests/api-gateway/example_test.go new file mode 100644 index 0000000000..b324ac31fe --- /dev/null +++ b/acceptance/tests/api-gateway/example_test.go @@ -0,0 +1,64 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Rename package to your test package. +package example + +import ( + "context" + "testing" + + "github.com/hashicorp/consul-k8s/acceptance/framework/consul" + "github.com/hashicorp/consul-k8s/acceptance/framework/helpers" + "github.com/hashicorp/consul-k8s/acceptance/framework/k8s" + "github.com/stretchr/testify/require" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestExample(t *testing.T) { + // Get test configuration. + cfg := suite.Config() + + // Get the default context. + ctx := suite.Environment().DefaultContext(t) + + // Create Helm values for the Helm install. + helmValues := map[string]string{ + "exampleFeature.enabled": "true", + } + + // Generate a random name for this test. + releaseName := helpers.RandomName() + + // Create a new Consul cluster object. + consulCluster := consul.NewHelmCluster(t, helmValues, ctx, cfg, releaseName) + + // Create the Consul cluster with Helm. + consulCluster.Create(t) + + // Make test assertions. + + // To run kubectl commands, you need to get KubectlOptions from the test context. + // There are a number of kubectl commands available in the helpers/kubectl.go file. + // For example, to call 'kubectl apply' from the test write the following: + k8s.KubectlApply(t, ctx.KubectlOptions(t), "path/to/config") + + // Clean up any Kubernetes resources you have created + helpers.Cleanup(t, cfg.NoCleanupOnFailure, func() { + k8s.KubectlDelete(t, ctx.KubectlOptions(t), "path/to/config") + }) + + // Similarly, you can obtain Kubernetes client from your test context. + // You can use it to, for example, read all services in a namespace: + k8sClient := ctx.KubernetesClient(t) + services, err := k8sClient.CoreV1().Services(ctx.KubectlOptions(t).Namespace).List(context.Background(), metav1.ListOptions{}) + require.NoError(t, err) + require.NotNil(t, services.Items) + + // To make Consul API calls, you can get the Consul client from the consulCluster object, + // indicating whether the client needs to be secure or not (i.e. whether TLS and ACLs are enabled on the Consul cluster): + consulClient, _ := consulCluster.SetupConsulClient(t, true) + consulServices, _, err := consulClient.Catalog().Services(nil) + require.NoError(t, err) + require.NotNil(t, consulServices) +} diff --git a/acceptance/tests/api-gateway/main_test.go b/acceptance/tests/api-gateway/main_test.go new file mode 100644 index 0000000000..f92fff8a59 --- /dev/null +++ b/acceptance/tests/api-gateway/main_test.go @@ -0,0 +1,37 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Rename package to your test package. +package example + +import ( + "testing" + + testsuite "github.com/hashicorp/consul-k8s/acceptance/framework/suite" +) + +var suite testsuite.Suite + +func TestMain(m *testing.M) { + // First, uncomment the line below to create a new suite so that all flags are parsed. + /* + suite = framework.NewSuite(m) + */ + + // If the test suite needs to run only when certain test flags are passed, + // you need to handle that in the TestMain function. + // Uncomment and modify example code below if that is the case. + /* + if suite.Config().EnableExampleFeature { + os.Exit(suite.Run()) + } else { + fmt.Println("Skipping example feature tests because -enable-example-feature is not set") + os.Exit(0) + } + */ + + // If the test suite should run in every case, uncomment the line below. + /* + os.Exit(suite.Run()) + */ +} From 13e778fa5371e7a29184b34887ff1cbabf9bb37f Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Fri, 26 May 2023 13:52:27 -0400 Subject: [PATCH 232/235] backport of commit 35593ca1be5cc2dff5209efd8d794c074dce5843 (#2190) Co-authored-by: Curt Bushko --- Makefile | 18 +- .../build-support/functions/10-util.sh | 1690 ++++++++--------- .../build-support/scripts/consul-version.sh | 3 +- 3 files changed, 833 insertions(+), 878 deletions(-) diff --git a/Makefile b/Makefile index ea94b303e9..c6e060a7de 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ VERSION = $(shell ./control-plane/build-support/scripts/version.sh control-plane/version/version.go) -CONSUL_VERSION = $(shell ./control-plane/build-support/scripts/consul-version.sh charts/consul/values.yaml) +CONSUL_IMAGE_VERSION = $(shell ./control-plane/build-support/scripts/consul-version.sh charts/consul/values.yaml) # ===========> Helm Targets @@ -149,8 +149,7 @@ version: @echo $(VERSION) consul-version: - @echo $(CONSUL_VERSION) - + @echo $(CONSUL_IMAGE_VERSION) # ===========> Release Targets @@ -161,7 +160,13 @@ endif ifndef RELEASE_DATE $(error RELEASE_DATE is required, use format , (ex. October 4, 2022)) endif - source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_release $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(LAST_RELEASE_GIT_TAG) $(PRERELEASE_VERSION) +ifndef LAST_RELEASE_GIT_TAG + $(error LAST_RELEASE_GIT_TAG is required) +endif +ifndef CONSUL_VERSION + $(error CONSUL_VERSION is required) +endif + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_release $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(LAST_RELEASE_GIT_TAG) $(CONSUL_VERSION) $(PRERELEASE_VERSION) prepare-dev: ifndef RELEASE_VERSION @@ -173,7 +178,10 @@ endif ifndef NEXT_RELEASE_VERSION $(error NEXT_RELEASE_VERSION is required) endif - source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_dev $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" $(NEXT_RELEASE_VERSION) +ifndef NEXT_CONSUL_VERSION + $(error NEXT_CONSUL_VERSION is required) +endif + source $(CURDIR)/control-plane/build-support/scripts/functions.sh; prepare_dev $(CURDIR) $(RELEASE_VERSION) "$(RELEASE_DATE)" "" $(NEXT_RELEASE_VERSION) $(NEXT_CONSUL_VERSION) # ===========> Makefile config diff --git a/control-plane/build-support/functions/10-util.sh b/control-plane/build-support/functions/10-util.sh index 8367c22743..c0f63df534 100644 --- a/control-plane/build-support/functions/10-util.sh +++ b/control-plane/build-support/functions/10-util.sh @@ -1,982 +1,930 @@ function err { - if test "${COLORIZE}" -eq 1 - then - tput bold - tput setaf 1 - fi + if test "${COLORIZE}" -eq 1; then + tput bold + tput setaf 1 + fi - echo "$@" 1>&2 + echo "$@" 1>&2 - if test "${COLORIZE}" -eq 1 - then - tput sgr0 - fi + if test "${COLORIZE}" -eq 1; then + tput sgr0 + fi } function status { - if test "${COLORIZE}" -eq 1 - then - tput bold - tput setaf 4 - fi + if test "${COLORIZE}" -eq 1; then + tput bold + tput setaf 4 + fi - echo "$@" + echo "$@" - if test "${COLORIZE}" -eq 1 - then - tput sgr0 - fi + if test "${COLORIZE}" -eq 1; then + tput sgr0 + fi } function status_stage { - if test "${COLORIZE}" -eq 1 - then - tput bold - tput setaf 2 - fi + if test "${COLORIZE}" -eq 1; then + tput bold + tput setaf 2 + fi - echo "$@" + echo "$@" - if test "${COLORIZE}" -eq 1 - then - tput sgr0 - fi + if test "${COLORIZE}" -eq 1; then + tput sgr0 + fi } function debug { - if is_set "${BUILD_DEBUG}" - then - if test "${COLORIZE}" -eq 1 - then - tput setaf 6 - fi - echo "$@" - if test "${COLORIZE}" -eq 1 - then - tput sgr0 - fi - fi + if is_set "${BUILD_DEBUG}"; then + if test "${COLORIZE}" -eq 1; then + tput setaf 6 + fi + echo "$@" + if test "${COLORIZE}" -eq 1; then + tput sgr0 + fi + fi } function sed_i { - if test "$(uname)" == "Darwin" - then - sed -i '' "$@" - return $? - else - sed -i "$@" - return $? - fi + if test "$(uname)" == "Darwin"; then + sed -i '' "$@" + return $? + else + sed -i "$@" + return $? + fi } function is_set { - # Arguments: - # $1 - string value to check its truthiness - # - # Return: - # 0 - is truthy (backwards I know but allows syntax like `if is_set ` to work) - # 1 - is not truthy - - local val=$(tr '[:upper:]' '[:lower:]' <<< "$1") - case $val in - 1 | t | true | y | yes) - return 0 - ;; - *) - return 1 - ;; - esac + # Arguments: + # $1 - string value to check its truthiness + # + # Return: + # 0 - is truthy (backwards I know but allows syntax like `if is_set ` to work) + # 1 - is not truthy + + local val=$(tr '[:upper:]' '[:lower:]' <<<"$1") + case $val in + 1 | t | true | y | yes) + return 0 + ;; + *) + return 1 + ;; + esac } function have_gpg_key { - # Arguments: - # $1 - GPG Key id to check if we have installed - # - # Return: - # 0 - success (we can use this key for signing) - # * - failure (key cannot be used) - - gpg --list-secret-keys $1 > /dev/null 2>&1 - return $? + # Arguments: + # $1 - GPG Key id to check if we have installed + # + # Return: + # 0 - success (we can use this key for signing) + # * - failure (key cannot be used) + + gpg --list-secret-keys $1 >/dev/null 2>&1 + return $? } function parse_version { - # Arguments: - # $1 - Path to the top level Consul source - # $2 - boolean value for whether the release version should be parsed from the source - # $3 - boolean whether to use GIT_DESCRIBE and GIT_COMMIT environment variables - # $4 - boolean whether to omit the version part of the version string. (optional) - # - # Return: - # 0 - success (will write the version to stdout) - # * - error (no version output) - # - # Notes: - # If the GOTAGS environment variable is present then it is used to determine which - # version file to use for parsing. - - local vfile="${1}/version/version.go" - - # ensure the version file exists - if ! test -f "${vfile}" - then - err "Error - File not found: ${vfile}" - return 1 - fi - - local include_release="$2" - local use_git_env="$3" - local omit_version="$4" - - local git_version="" - local git_commit="" - - if test -z "${include_release}" - then - include_release=true - fi - - if test -z "${use_git_env}" - then - use_git_env=true - fi - - if is_set "${use_git_env}" - then - git_version="${GIT_DESCRIBE}" - git_commit="${GIT_COMMIT}" - fi - - # Get the main version out of the source file - version_main=$(awk '$1 == "Version" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < ${vfile}) - release_main=$(awk '$1 == "VersionPrerelease" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < ${vfile}) - - - # try to determine the version if we have build tags - for tag in "$GOTAGS" - do - for vfile in $(find "${1}/version" -name "version_*.go" 2> /dev/null| sort) - do - if grep -q "// +build $tag" "${vfile}" - then - version_main=$(awk '$1 == "Version" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < ${vfile}) - release_main=$(awk '$1 == "VersionPrerelease" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < ${vfile}) - fi - done - done - - local version="${version_main}" - # override the version from source with the value of the GIT_DESCRIBE env var if present - if test -n "${git_version}" - then - version="${git_version}" - fi - - local rel_ver="" - if is_set "${include_release}" - then - # Default to pre-release from the source - rel_ver="${release_main}" - - # When no GIT_DESCRIBE env var is present and no release is in the source then we - # are definitely in dev mode - if test -z "${git_version}" -a -z "${rel_ver}" && is_set "${use_git_env}" - then - rel_ver="dev" - fi - - # Add the release to the version - if test -n "${rel_ver}" -a -n "${git_commit}" - then - rel_ver="${rel_ver} (${git_commit})" - fi - fi - - if test -n "${rel_ver}" - then - if is_set "${omit_version}" - then - echo "${rel_ver}" | tr -d "'" - else - echo "${version}-${rel_ver}" | tr -d "'" - fi - return 0 - elif ! is_set "${omit_version}" - then - echo "${version}" | tr -d "'" - return 0 - else - return 1 - fi + # Arguments: + # $1 - Path to the top level Consul source + # $2 - boolean value for whether the release version should be parsed from the source + # $3 - boolean whether to use GIT_DESCRIBE and GIT_COMMIT environment variables + # $4 - boolean whether to omit the version part of the version string. (optional) + # + # Return: + # 0 - success (will write the version to stdout) + # * - error (no version output) + # + # Notes: + # If the GOTAGS environment variable is present then it is used to determine which + # version file to use for parsing. + + local vfile="${1}/version/version.go" + + # ensure the version file exists + if ! test -f "${vfile}"; then + err "Error - File not found: ${vfile}" + return 1 + fi + + local include_release="$2" + local use_git_env="$3" + local omit_version="$4" + + local git_version="" + local git_commit="" + + if test -z "${include_release}"; then + include_release=true + fi + + if test -z "${use_git_env}"; then + use_git_env=true + fi + + if is_set "${use_git_env}"; then + git_version="${GIT_DESCRIBE}" + git_commit="${GIT_COMMIT}" + fi + + # Get the main version out of the source file + version_main=$(awk '$1 == "Version" && $2 == "=" { gsub(/"/, "", $3); print $3 }' <${vfile}) + release_main=$(awk '$1 == "VersionPrerelease" && $2 == "=" { gsub(/"/, "", $3); print $3 }' <${vfile}) + + # try to determine the version if we have build tags + for tag in "$GOTAGS"; do + for vfile in $(find "${1}/version" -name "version_*.go" 2>/dev/null | sort); do + if grep -q "// +build $tag" "${vfile}"; then + version_main=$(awk '$1 == "Version" && $2 == "=" { gsub(/"/, "", $3); print $3 }' <${vfile}) + release_main=$(awk '$1 == "VersionPrerelease" && $2 == "=" { gsub(/"/, "", $3); print $3 }' <${vfile}) + fi + done + done + + local version="${version_main}" + # override the version from source with the value of the GIT_DESCRIBE env var if present + if test -n "${git_version}"; then + version="${git_version}" + fi + + local rel_ver="" + if is_set "${include_release}"; then + # Default to pre-release from the source + rel_ver="${release_main}" + + # When no GIT_DESCRIBE env var is present and no release is in the source then we + # are definitely in dev mode + if test -z "${git_version}" -a -z "${rel_ver}" && is_set "${use_git_env}"; then + rel_ver="dev" + fi + + # Add the release to the version + if test -n "${rel_ver}" -a -n "${git_commit}"; then + rel_ver="${rel_ver} (${git_commit})" + fi + fi + + if test -n "${rel_ver}"; then + if is_set "${omit_version}"; then + echo "${rel_ver}" | tr -d "'" + else + echo "${version}-${rel_ver}" | tr -d "'" + fi + return 0 + elif ! is_set "${omit_version}"; then + echo "${version}" | tr -d "'" + return 0 + else + return 1 + fi } function get_version { - # Arguments: - # $1 - Path to the top level Consul source - # $2 - Whether the release version should be parsed from source (optional) - # $3 - Whether to use GIT_DESCRIBE and GIT_COMMIT environment variables - # - # Returns: - # 0 - success (the version is also echoed to stdout) - # 1 - error - # - # Notes: - # If a VERSION environment variable is present it will override any parsing of the version from the source - # In addition to processing the main version.go, version_*.go files will be processed if they have - # a Go build tag that matches the one in the GOTAGS environment variable. This tag processing is - # primitive though and will not match complex build tags in the files with negation etc. - - local vers="$VERSION" - if test -z "$vers" - then - # parse the OSS version from version.go - vers="$(parse_version ${1} ${2} ${3})" - fi - - if test -z "$vers" - then - return 1 - else - echo $vers - return 0 - fi + # Arguments: + # $1 - Path to the top level Consul source + # $2 - Whether the release version should be parsed from source (optional) + # $3 - Whether to use GIT_DESCRIBE and GIT_COMMIT environment variables + # + # Returns: + # 0 - success (the version is also echoed to stdout) + # 1 - error + # + # Notes: + # If a VERSION environment variable is present it will override any parsing of the version from the source + # In addition to processing the main version.go, version_*.go files will be processed if they have + # a Go build tag that matches the one in the GOTAGS environment variable. This tag processing is + # primitive though and will not match complex build tags in the files with negation etc. + + local vers="$VERSION" + if test -z "$vers"; then + # parse the OSS version from version.go + vers="$(parse_version ${1} ${2} ${3})" + fi + + if test -z "$vers"; then + return 1 + else + echo $vers + return 0 + fi } function git_branch { - # Arguments: - # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) - # - # Returns: - # 0 - success - # * - failure - # - # Notes: - # Echos the current branch to stdout when successful - - local gdir="$(pwd)" - if test -d "$1" - then - gdir="$1" - fi - - pushd "${gdir}" > /dev/null - - local ret=0 - local head="$(git status -b --porcelain=v2 | awk '{if ($1 == "#" && $2 =="branch.head") { print $3 }}')" || ret=1 - - popd > /dev/null - - test ${ret} -eq 0 && echo "$head" - return ${ret} + # Arguments: + # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) + # + # Returns: + # 0 - success + # * - failure + # + # Notes: + # Echos the current branch to stdout when successful + + local gdir="$(pwd)" + if test -d "$1"; then + gdir="$1" + fi + + pushd "${gdir}" >/dev/null + + local ret=0 + local head="$(git status -b --porcelain=v2 | awk '{if ($1 == "#" && $2 =="branch.head") { print $3 }}')" || ret=1 + + popd >/dev/null + + test ${ret} -eq 0 && echo "$head" + return ${ret} } function git_upstream { - # Arguments: - # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) - # - # Returns: - # 0 - success - # * - failure - # - # Notes: - # Echos the current upstream branch to stdout when successful - - local gdir="$(pwd)" - if test -d "$1" - then - gdir="$1" - fi - - pushd "${gdir}" > /dev/null - - local ret=0 - local head="$(git status -b --porcelain=v2 | awk '{if ($1 == "#" && $2 =="branch.upstream") { print $3 }}')" || ret=1 - - popd > /dev/null - - test ${ret} -eq 0 && echo "$head" - return ${ret} + # Arguments: + # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) + # + # Returns: + # 0 - success + # * - failure + # + # Notes: + # Echos the current upstream branch to stdout when successful + + local gdir="$(pwd)" + if test -d "$1"; then + gdir="$1" + fi + + pushd "${gdir}" >/dev/null + + local ret=0 + local head="$(git status -b --porcelain=v2 | awk '{if ($1 == "#" && $2 =="branch.upstream") { print $3 }}')" || ret=1 + + popd >/dev/null + + test ${ret} -eq 0 && echo "$head" + return ${ret} } function git_log_summary { - # Arguments: - # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) - # - # Returns: - # 0 - success - # * - failure - # + # Arguments: + # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) + # + # Returns: + # 0 - success + # * - failure + # - local gdir="$(pwd)" - if test -d "$1" - then - gdir="$1" - fi + local gdir="$(pwd)" + if test -d "$1"; then + gdir="$1" + fi - pushd "${gdir}" > /dev/null + pushd "${gdir}" >/dev/null - local ret=0 + local ret=0 - local head=$(git_branch) || ret=1 - local upstream=$(git_upstream) || ret=1 - local rev_range="${head}...${upstream}" + local head=$(git_branch) || ret=1 + local upstream=$(git_upstream) || ret=1 + local rev_range="${head}...${upstream}" - if test ${ret} -eq 0 - then - status "Git Changes:" - git log --pretty=oneline ${rev_range} || ret=1 + if test ${ret} -eq 0; then + status "Git Changes:" + git log --pretty=oneline ${rev_range} || ret=1 - fi - return $ret + fi + return $ret } function git_diff { - # Arguments: - # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) - # $2 .. $N - Optional path specification - # - # Returns: - # 0 - success - # * - failure - # - - local gdir="$(pwd)" - if test -d "$1" - then - gdir="$1" - fi - - shift - - pushd "${gdir}" > /dev/null - - local ret=0 - - local head=$(git_branch) || ret=1 - local upstream=$(git_upstream) || ret=1 - - if test ${ret} -eq 0 - then - status "Git Diff - Paths: $@" - git diff ${HEAD} ${upstream} -- "$@" || ret=1 - fi - return $ret + # Arguments: + # $1 - Path to the git repo (optional - assumes pwd is git repo otherwise) + # $2 .. $N - Optional path specification + # + # Returns: + # 0 - success + # * - failure + # + + local gdir="$(pwd)" + if test -d "$1"; then + gdir="$1" + fi + + shift + + pushd "${gdir}" >/dev/null + + local ret=0 + + local head=$(git_branch) || ret=1 + local upstream=$(git_upstream) || ret=1 + + if test ${ret} -eq 0; then + status "Git Diff - Paths: $@" + git diff ${HEAD} ${upstream} -- "$@" || ret=1 + fi + return $ret } function normalize_git_url { - url="${1#https://}" - url="${url#git@}" - url="${url%.git}" - url="$(sed ${SED_EXT} -e 's/([^\/:]*)[:\/](.*)/\1:\2/' <<< "${url}")" - echo "$url" - return 0 + url="${1#https://}" + url="${url#git@}" + url="${url%.git}" + url="$(sed ${SED_EXT} -e 's/([^\/:]*)[:\/](.*)/\1:\2/' <<<"${url}")" + echo "$url" + return 0 } function git_remote_url { - # Arguments: - # $1 - Path to the top level Consul source - # $2 - Remote name - # - # Returns: - # 0 - success - # * - error - # - # Note: - # The push url for the git remote will be echoed to stdout - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. git_remote_url must be called with the path to the top level source as the first argument'" - return 1 - fi - - if test -z "$2" - then - err "ERROR: git_remote_url must be called with a second argument that is the name of the remote" - return 1 - fi - - local ret=0 - - pushd "$1" > /dev/null - - local url=$(git remote get-url --push $2 2>&1) || ret=1 - - popd > /dev/null - - if test "${ret}" -eq 0 - then - echo "${url}" - return 0 - fi + # Arguments: + # $1 - Path to the top level Consul source + # $2 - Remote name + # + # Returns: + # 0 - success + # * - error + # + # Note: + # The push url for the git remote will be echoed to stdout + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. git_remote_url must be called with the path to the top level source as the first argument'" + return 1 + fi + + if test -z "$2"; then + err "ERROR: git_remote_url must be called with a second argument that is the name of the remote" + return 1 + fi + + local ret=0 + + pushd "$1" >/dev/null + + local url=$(git remote get-url --push $2 2>&1) || ret=1 + + popd >/dev/null + + if test "${ret}" -eq 0; then + echo "${url}" + return 0 + fi } function find_git_remote { - # Arguments: - # $1 - Path to the top level Consul source - # - # Returns: - # 0 - success - # * - error - # - # Note: - # The remote name to use for publishing will be echoed to stdout upon success - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. find_git_remote must be called with the path to the top level source as the first argument'" - return 1 - fi - - need_url=$(normalize_git_url "${PUBLISH_GIT_HOST}:${PUBLISH_GIT_REPO}") - debug "Required normalized remote: ${need_url}" - - pushd "$1" > /dev/null - - local ret=1 - for remote in $(git remote) - do - url=$(git remote get-url --push ${remote}) || continue - url=$(normalize_git_url "${url}") - - debug "Testing Remote: ${remote}: ${url}" - if test "${url}" == "${need_url}" - then - echo "${remote}" - ret=0 - break - fi - done - - popd > /dev/null - return ${ret} + # Arguments: + # $1 - Path to the top level Consul source + # + # Returns: + # 0 - success + # * - error + # + # Note: + # The remote name to use for publishing will be echoed to stdout upon success + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. find_git_remote must be called with the path to the top level source as the first argument'" + return 1 + fi + + need_url=$(normalize_git_url "${PUBLISH_GIT_HOST}:${PUBLISH_GIT_REPO}") + debug "Required normalized remote: ${need_url}" + + pushd "$1" >/dev/null + + local ret=1 + for remote in $(git remote); do + url=$(git remote get-url --push ${remote}) || continue + url=$(normalize_git_url "${url}") + + debug "Testing Remote: ${remote}: ${url}" + if test "${url}" == "${need_url}"; then + echo "${remote}" + ret=0 + break + fi + done + + popd >/dev/null + return ${ret} } function git_remote_not_blacklisted { - # Arguments: - # $1 - path to the repo - # $2 - the remote name - # - # Returns: - # 0 - not blacklisted - # * - blacklisted - return 0 + # Arguments: + # $1 - path to the repo + # $2 - the remote name + # + # Returns: + # 0 - not blacklisted + # * - blacklisted + return 0 } function is_git_clean { - # Arguments: - # $1 - Path to git repo - # $2 - boolean whether the git status should be output when not clean - # - # Returns: - # 0 - success - # * - error - # - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. is_git_clean must be called with the path to a git repo as the first argument'" - return 1 - fi - - local output_status="$2" - - pushd "${1}" > /dev/null - - local ret=0 - test -z "$(git status --porcelain=v2 2> /dev/null)" || ret=1 - - if is_set "${output_status}" && test "$ret" -ne 0 - then - err "Git repo is not clean" - # --porcelain=v1 is the same as --short except uncolorized - git status --porcelain=v1 - fi - popd > /dev/null - return ${ret} + # Arguments: + # $1 - Path to git repo + # $2 - boolean whether the git status should be output when not clean + # + # Returns: + # 0 - success + # * - error + # + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. is_git_clean must be called with the path to a git repo as the first argument'" + return 1 + fi + + local output_status="$2" + + pushd "${1}" >/dev/null + + local ret=0 + test -z "$(git status --porcelain=v2 2>/dev/null)" || ret=1 + + if is_set "${output_status}" && test "$ret" -ne 0; then + err "Git repo is not clean" + # --porcelain=v1 is the same as --short except uncolorized + git status --porcelain=v1 + fi + popd >/dev/null + return ${ret} } function update_git_env { - # Arguments: - # $1 - Path to git repo - # - # Returns: - # 0 - success - # * - error - # - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. is_git_clean must be called with the path to a git repo as the first argument'" - return 1 - fi - - export GIT_COMMIT=$(git rev-parse --short HEAD) - export GIT_DIRTY=$(test -n "$(git status --porcelain)" && echo "+CHANGES") - export GIT_DESCRIBE=$(git describe --tags --always) - export GIT_IMPORT=github.com/hashicorp/consul-k8s/version - export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${GIT_IMPORT}.GitDescribe=${GIT_DESCRIBE}" - return 0 + # Arguments: + # $1 - Path to git repo + # + # Returns: + # 0 - success + # * - error + # + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. is_git_clean must be called with the path to a git repo as the first argument'" + return 1 + fi + + export GIT_COMMIT=$(git rev-parse --short HEAD) + export GIT_DIRTY=$(test -n "$(git status --porcelain)" && echo "+CHANGES") + export GIT_DESCRIBE=$(git describe --tags --always) + export GIT_IMPORT=github.com/hashicorp/consul-k8s/version + export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${GIT_IMPORT}.GitDescribe=${GIT_DESCRIBE}" + return 0 } function git_push_ref { - # Arguments: - # $1 - Path to the top level Consul source - # $2 - Git ref (optional) - # $3 - remote (optional - if not specified we will try to determine it) - # - # Returns: - # 0 - success - # * - error - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. push_git_release must be called with the path to the top level source as the first argument'" - return 1 - fi - - local sdir="$1" - local ret=0 - local remote="$3" - - # find the correct remote corresponding to the desired repo (basically prevent pushing enterprise to oss or oss to enterprise) - if test -z "${remote}" - then - local remote=$(find_git_remote "${sdir}") || return 1 - status "Using git remote: ${remote}" - fi - - local ref="" - - pushd "${sdir}" > /dev/null - - if test -z "$2" - then - # If no git ref was provided we lookup the current local branch and its tracking branch - # It must have a tracking upstream and it must be tracking the sanctioned git remote - local head=$(git_branch "${sdir}") || return 1 - local upstream=$(git_upstream "${sdir}") || return 1 - - # upstream branch for this branch does not track the remote we need to push to - # basically this checks that the upstream (could be something like origin/main) references the correct remote - # if it doesn't then the string modification wont apply and the var will reamin unchanged and equal to itself. - if test "${upstream#${remote}/}" == "${upstream}" - then - err "ERROR: Upstream branch '${upstream}' does not track the correct remote '${remote}' - cannot push" - ret=1 - fi - ref="refs/heads/${head}" - else - # A git ref was provided - get the full ref and make sure it isn't ambiguous and also to - # be able to determine whether its a branch or tag we are pushing - ref_out=$(git rev-parse --symbolic-full-name "$2" --) - - # -ne 2 because it should have the ref on one line followed by a line with '--' - if test "$(wc -l <<< "${ref_out}")" -ne 2 - then - err "ERROR: Git ref '$2' is ambiguous" - debug "${ref_out}" - ret=1 - else - ref=$(head -n 1 <<< "${ref_out}") - fi - fi - - if test ${ret} -eq 0 - then - case "${ref}" in - refs/tags/*) - status "Pushing tag ${ref#refs/tags/} to ${remote}" - ;; - refs/heads/*) - status "Pushing local branch ${ref#refs/tags/} to ${remote}" - ;; - *) - err "ERROR: git_push_ref func is refusing to push ref that isn't a branch or tag" - return 1 - esac - - if ! git push "${remote}" "${ref}" - then - err "ERROR: Failed to push ${ref} to remote: ${remote}" - ret=1 - fi - fi - - popd > /dev/null - - return $ret + # Arguments: + # $1 - Path to the top level Consul source + # $2 - Git ref (optional) + # $3 - remote (optional - if not specified we will try to determine it) + # + # Returns: + # 0 - success + # * - error + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. push_git_release must be called with the path to the top level source as the first argument'" + return 1 + fi + + local sdir="$1" + local ret=0 + local remote="$3" + + # find the correct remote corresponding to the desired repo (basically prevent pushing enterprise to oss or oss to enterprise) + if test -z "${remote}"; then + local remote=$(find_git_remote "${sdir}") || return 1 + status "Using git remote: ${remote}" + fi + + local ref="" + + pushd "${sdir}" >/dev/null + + if test -z "$2"; then + # If no git ref was provided we lookup the current local branch and its tracking branch + # It must have a tracking upstream and it must be tracking the sanctioned git remote + local head=$(git_branch "${sdir}") || return 1 + local upstream=$(git_upstream "${sdir}") || return 1 + + # upstream branch for this branch does not track the remote we need to push to + # basically this checks that the upstream (could be something like origin/main) references the correct remote + # if it doesn't then the string modification wont apply and the var will reamin unchanged and equal to itself. + if test "${upstream#${remote}/}" == "${upstream}"; then + err "ERROR: Upstream branch '${upstream}' does not track the correct remote '${remote}' - cannot push" + ret=1 + fi + ref="refs/heads/${head}" + else + # A git ref was provided - get the full ref and make sure it isn't ambiguous and also to + # be able to determine whether its a branch or tag we are pushing + ref_out=$(git rev-parse --symbolic-full-name "$2" --) + + # -ne 2 because it should have the ref on one line followed by a line with '--' + if test "$(wc -l <<<"${ref_out}")" -ne 2; then + err "ERROR: Git ref '$2' is ambiguous" + debug "${ref_out}" + ret=1 + else + ref=$(head -n 1 <<<"${ref_out}") + fi + fi + + if test ${ret} -eq 0; then + case "${ref}" in + refs/tags/*) + status "Pushing tag ${ref#refs/tags/} to ${remote}" + ;; + refs/heads/*) + status "Pushing local branch ${ref#refs/tags/} to ${remote}" + ;; + *) + err "ERROR: git_push_ref func is refusing to push ref that isn't a branch or tag" + return 1 + ;; + esac + + if ! git push "${remote}" "${ref}"; then + err "ERROR: Failed to push ${ref} to remote: ${remote}" + ret=1 + fi + fi + + popd >/dev/null + + return $ret } function update_version { - # Arguments: - # $1 - Path to the version file - # $2 - Version string - # $3 - PreRelease version (if unset will become an empty string) - # - # Returns: - # 0 - success - # * - error - - if ! test -f "$1" - then - err "ERROR: '$1' is not a regular file. update_version must be called with the path to a go version file" - return 1 - fi - - if test -z "$2" - then - err "ERROR: The version specified was empty" - return 1 - fi - - local vfile="$1" - local version="$2" - local prerelease="$3" - - sed_i ${SED_EXT} -e "s/(Version[[:space:]]*=[[:space:]]*)\"[^\"]*\"/\1\"${version}\"/g" -e "s/(VersionPrerelease[[:space:]]*=[[:space:]]*)\"[^\"]*\"/\1\"${prerelease}\"/g" "${vfile}" - return $? + # Arguments: + # $1 - Path to the version file + # $2 - Version string + # $3 - PreRelease version (if unset will become an empty string) + # + # Returns: + # 0 - success + # * - error + + if ! test -f "$1"; then + err "ERROR: '$1' is not a regular file. update_version must be called with the path to a go version file" + return 1 + fi + + if test -z "$2"; then + err "ERROR: The version specified was empty" + return 1 + fi + + local vfile="$1" + local version="$2" + local prerelease="$3" + + sed_i ${SED_EXT} -e "s/(Version[[:space:]]*=[[:space:]]*)\"[^\"]*\"/\1\"${version}\"/g" -e "s/(VersionPrerelease[[:space:]]*=[[:space:]]*)\"[^\"]*\"/\1\"${prerelease}\"/g" "${vfile}" + return $? } function update_version_helm { - # Arguments: - # $1 - Path to the directory where the root of the Helm chart is - # $2 - Version string - # $3 - PreRelease version (if unset will become an empty string) - # $4 - Image base path - # - # Returns: - # 0 - success - # * - error - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. update_version_helm must be called with the path to the Helm chart" - return 1 - fi - - if test -z "$2" - then - err "ERROR: The version specified was empty" - return 1 - fi - - local vfile="$1/values.yaml" - local cfile="$1/Chart.yaml" - local version="$2" - local prerelease="$3" - local full_version="$2" - if ! test -z "$3" - then - full_version="$2-$3" - fi - - sed_i ${SED_EXT} -e "s/(imageK8S:.*\/consul-k8s-control-plane:)[^\"]*/imageK8S: $4${full_version}/g" "${vfile}" - sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version}/g" "${cfile}" - sed_i ${SED_EXT} -e "s/(image:.*\/consul-k8s-control-plane:)[^\"]*/image: $4${full_version}/g" "${cfile}" - - if test -z "$3" - then - sed_i ${SED_EXT} -e "s/(artifacthub.io\/prerelease:[[:space:]]*)[^\"]*/\1false/g" "${cfile}" - else - sed_i ${SED_EXT} -e "s/(artifacthub.io\/prerelease:[[:space:]]*)[^\"]*/\1true/g" "${cfile}" - fi - return $? + # Arguments: + # $1 - Path to the directory where the root of the Helm chart is + # $2 - Version string + # $3 - Release version (if unset will become an empty string) + # $4 - Image base path + # $5 - Consul version string + # $6 - Consul image base path + # + # Returns: + # 0 - success + # * - error + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. update_version_helm must be called with the path to the Helm chart" + return 1 + fi + + if test -z "$2"; then + err "ERROR: The version specified was empty" + return 1 + fi + + local vfile="$1/values.yaml" + local cfile="$1/Chart.yaml" + local version="$2" + local consul_version="$5" + local prerelease="$3" + local full_version="$2" + local full_consul_version="$5" + if ! test -z "$3"; then + full_version="$2-$3" + # strip off the last minor patch version so that the consul image can be set to something like 1.16-dev. The image + # is produced by Consul every night + full_consul_version="${5%.*}-$3" + fi + + sed_i ${SED_EXT} -e "s/(imageK8S:.*\/consul-k8s-control-plane:)[^\"]*/imageK8S: $4${full_version}/g" "${vfile}" + sed_i ${SED_EXT} -e "s/(version:[[:space:]]*)[^\"]*/\1${full_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(appVersion:[[:space:]]*)[^\"]*/\1${full_consul_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(image:.*\/consul-k8s-control-plane:)[^\"]*/image: $4${full_version}/g" "${cfile}" + if ! test -z "$3"; then + sed_i ${SED_EXT} -e "s/(image:.*\/consul:)[^\"]*/image: $6:${full_consul_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(image:.*\/consul:)[^\"]*/image: $6:${full_consul_version}/g" "${vfile}" + else + sed_i ${SED_EXT} -e "s/(image:.*\/consul-enterprise:)[^\"]*/image: $6:${full_consul_version}/g" "${cfile}" + sed_i ${SED_EXT} -e "s/(image:.*\/consul-enterprise:)[^\"]*/image: $6:${full_consul_version}/g" "${vfile}" + fi + + if test -z "$3"; then + sed_i ${SED_EXT} -e "s/(artifacthub.io\/prerelease:[[:space:]]*)[^\"]*/\1false/g" "${cfile}" + else + sed_i ${SED_EXT} -e "s/(artifacthub.io\/prerelease:[[:space:]]*)[^\"]*/\1true/g" "${cfile}" + fi + return $? } function set_version { - # Arguments: - # $1 - Path to top level Consul source - # $2 - The version of the release - # $3 - The release date - # $4 - The pre-release version - # $5 - The helm docker image base path - # - # - # Returns: - # 0 - success - # * - error - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. prepare_release must be called with the path to a git repo as the first argument" - return 1 - fi - - if test -z "$2" - then - err "ERROR: The version specified was empty" - return 1 - fi - - local sdir="$1" - local vers="$2" - - status_stage "==> Updating control-plane version/version.go with version info: ${vers} "$4"" - if ! update_version "${sdir}/control-plane/version/version.go" "${vers}" "$4" - then - return 1 - fi - - status_stage "==> Updating cli version/version.go with version info: ${vers} "$4"" - if ! update_version "${sdir}/cli/version/version.go" "${vers}" "$4" - then - return 1 - fi - - status_stage "==> Updating Helm chart versions with version info: ${vers} "$4"" - if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" "$5" - then - return 1 - fi - - return 0 + # Arguments: + # $1 - Path to top level Consul source + # $2 - The version of the release + # $3 - The release date + # $4 - The pre-release version + # $5 - The consul-k8s helm docker image base path + # $6 - The consul version + # $7 - The consul helm docker image base path + # + # + # Returns: + # 0 - success + # * - error + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. prepare_release must be called with the path to a git repo as the first argument" + return 1 + fi + + if test -z "$2"; then + err "ERROR: The version specified was empty" + return 1 + fi + + local sdir="$1" + local vers="$2" + local consul_vers="$6" + + status_stage "==> Updating control-plane version/version.go with version info: ${vers} "$4"" + if ! update_version "${sdir}/control-plane/version/version.go" "${vers}" "$4"; then + return 1 + fi + + status_stage "==> Updating cli version/version.go with version info: ${vers} "$4"" + if ! update_version "${sdir}/cli/version/version.go" "${vers}" "$4"; then + return 1 + fi + + status_stage "==> Updating Helm chart version, consul-k8s: ${vers} "$4" consul: ${consul_vers} "$4"" + if ! update_version_helm "${sdir}/charts/consul" "${vers}" "$4" "$5" "${consul_vers}" "$7"; then + return 1 + fi + + return 0 } function set_changelog { - # Arguments: - # $1 - Path to top level Consul source - # $2 - Version - # $3 - Release Date - # $4 - The last git release tag - # - # - # Returns: - # 0 - success - # * - error - - # Check if changelog-build is installed - if ! command -v changelog-build &> /dev/null; then - echo "Error: changelog-build is not installed. Please install it and try again." - exit 1 - fi - - local curdir="$1" - local version="$2" - local rel_date="$(date +"%B %d, %Y")" - if test -n "$3" - then - rel_date="$3" - fi - local last_release_date_git_tag=$4 - - if test -z "${version}" - then - err "ERROR: Must specify a version to put into the changelog" - return 1 - fi - - if [ -z "$LAST_RELEASE_GIT_TAG" ]; then - echo "Error: LAST_RELEASE_GIT_TAG not specified." - exit 1 - fi - -cat < tmp && mv tmp "${curdir}"/CHANGELOG.MD + # Arguments: + # $1 - Path to top level Consul source + # $2 - Version + # $3 - Release Date + # $4 - The last git release tag + # + # + # Returns: + # 0 - success + # * - error + + # Check if changelog-build is installed + if ! command -v changelog-build &>/dev/null; then + echo "Error: changelog-build is not installed. Please install it and try again." + exit 1 + fi + + local curdir="$1" + local version="$2" + local rel_date="$(date +"%B %d, %Y")" + if test -n "$3"; then + rel_date="$3" + fi + local last_release_date_git_tag=$4 + + if test -z "${version}"; then + err "ERROR: Must specify a version to put into the changelog" + return 1 + fi + + if [ -z "$LAST_RELEASE_GIT_TAG" ]; then + echo "Error: LAST_RELEASE_GIT_TAG not specified." + exit 1 + fi + + cat <tmp && mv tmp "${curdir}"/CHANGELOG.MD ## ${version} (${rel_date}) $(changelog-build -last-release ${LAST_RELEASE_GIT_TAG} \ - -entries-dir .changelog/ \ - -changelog-template .changelog/changelog.tmpl \ - -note-template .changelog/note.tmpl \ - -this-release $(git rev-parse HEAD)) + -entries-dir .changelog/ \ + -changelog-template .changelog/changelog.tmpl \ + -note-template .changelog/note.tmpl \ + -this-release $(git rev-parse HEAD)) EOT } function prepare_release { - # Arguments: - # $1 - Path to top level Consul source - # $2 - The version of the release - # $3 - The release date - # $4 - The last release git tag for this branch (eg. v1.1.0) - # $5 - The pre-release version - # - # - # Returns: - # 0 - success - # * - error - - echo "release version: " "$1" "$2" "$3" "$4" - set_version "$1" "$2" "$3" "$5" "hashicorp\/consul-k8s-control-plane:" - set_changelog "$1" "$2" "$3" "$4" + # Arguments: + # $1 - Path to top level Consul source + # $2 - The version of the release + # $3 - The release date + # $4 - The last release git tag for this branch (eg. v1.1.0) + # $5 - The pre-release version + # $6 - The consul version + # + # + # Returns: + # 0 - success + # * - error + + echo "prepare_release: dir:$1 consul-k8s:$2 consul:$5 date:"$3" git tag:$4" + set_version "$1" "$2" "$3" "$6" "hashicorp\/consul-k8s-control-plane:" "$5" "hashicorp\/consul" + set_changelog "$1" "$2" "$3" "$4" } function prepare_dev { - # Arguments: - # $1 - Path to top level Consul source - # $2 - The version of the release - # $3 - The release date - # $4 - The version of the next release - # $5 - The last release git tag for this branch (eg. v1.1.0) - # - # Returns: - # 0 - success - # * - error - - echo "dev version: " $1 $4 $3 "dev" - set_version "$1" "$4" "$3" "dev" "docker.mirror.hashicorp.services\/hashicorppreview\/consul-k8s-control-plane:" - - return 0 + # Arguments: + # $1 - Path to top level Consul source + # $2 - The version of the release + # $3 - The release date + # $4 - The last release git tag for this branch (eg. v1.1.0) (Unused) + # $5 - The version of the next release + # $6 - The version of the next consul release + # + # Returns: + # 0 - success + # * - error + + echo "prepare_dev: dir:$1 consul-k8s:$5 consul:$6 date:"$3" mode:dev" + set_version "$1" "$5" "$3" "dev" "docker.mirror.hashicorp.services\/hashicorppreview\/consul-k8s-control-plane:" "$6" "docker.mirror.hashicorp.services\/hashicorppreview\/consul-enterprise" + + return 0 } function git_staging_empty { - # Arguments: - # $1 - Path to git repo - # - # Returns: - # 0 - success (nothing staged) - # * - error (staged files) - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. commit_dev_mode must be called with the path to a git repo as the first argument'" - return 1 - fi - - pushd "$1" > /dev/null - - declare -i ret=0 - - for status in $(git status --porcelain=v2 | awk '{print $2}' | cut -b 1) - do - if test "${status}" != "." - then - ret=1 - break - fi - done - - popd > /dev/null - return ${ret} + # Arguments: + # $1 - Path to git repo + # + # Returns: + # 0 - success (nothing staged) + # * - error (staged files) + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. commit_dev_mode must be called with the path to a git repo as the first argument'" + return 1 + fi + + pushd "$1" >/dev/null + + declare -i ret=0 + + for status in $(git status --porcelain=v2 | awk '{print $2}' | cut -b 1); do + if test "${status}" != "."; then + ret=1 + break + fi + done + + popd >/dev/null + return ${ret} } function commit_dev_mode { - # Arguments: - # $1 - Path to top level Consul source - # - # Returns: - # 0 - success - # * - error + # Arguments: + # $1 - Path to top level Consul source + # + # Returns: + # 0 - success + # * - error - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory. commit_dev_mode must be called with the path to a git repo as the first argument'" - return 1 - fi + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory. commit_dev_mode must be called with the path to a git repo as the first argument'" + return 1 + fi - status "Checking for previously staged files" - git_staging_empty "$1" || return 1 + status "Checking for previously staged files" + git_staging_empty "$1" || return 1 - declare -i ret=0 + declare -i ret=0 - pushd "$1" > /dev/null + pushd "$1" >/dev/null - status "Staging CHANGELOG.md and version_*.go files" - git add CHANGELOG.md && git add */version/version*.go - ret=$? + status "Staging CHANGELOG.md and version_*.go files" + git add CHANGELOG.md && git add */version/version*.go + ret=$? - if test ${ret} -eq 0 - then - status "Adding Commit" - git commit -m "Putting source back into Dev Mode" - ret=$? - fi + if test ${ret} -eq 0; then + status "Adding Commit" + git commit -m "Putting source back into Dev Mode" + ret=$? + fi - popd >/dev/null - return ${ret} + popd >/dev/null + return ${ret} } function gpg_detach_sign { - # Arguments: - # $1 - File to sign - # $2 - Alternative GPG key to use for signing - # - # Returns: - # 0 - success - # * - failure - - # determine whether the gpg key to use is being overridden - local gpg_key=${HASHICORP_GPG_KEY} - if test -n "$2" - then - gpg_key=$2 - fi - - gpg --default-key "${gpg_key}" --detach-sig --yes -v "$1" - return $? + # Arguments: + # $1 - File to sign + # $2 - Alternative GPG key to use for signing + # + # Returns: + # 0 - success + # * - failure + + # determine whether the gpg key to use is being overridden + local gpg_key=${HASHICORP_GPG_KEY} + if test -n "$2"; then + gpg_key=$2 + fi + + gpg --default-key "${gpg_key}" --detach-sig --yes -v "$1" + return $? } function shasum_directory { - # Arguments: - # $1 - Path to directory containing the files to shasum - # $2 - File to output sha sums to - # - # Returns: - # 0 - success - # * - failure - - if ! test -d "$1" - then - err "ERROR: '$1' is not a directory and shasum_release requires passing a directory as the first argument" - return 1 - fi - - if test -z "$2" - then - err "ERROR: shasum_release requires a second argument to be the filename to output the shasums to but none was given" - return 1 - fi - - pushd $1 > /dev/null - shasum -a256 * > "$2" - ret=$? - popd >/dev/null - - return $ret -} - - function ui_version { - # Arguments: - # $1 - path to index.html - # - # Returns: - # 0 - success - # * -failure - # - # Notes: echoes the version to stdout upon success - if ! test -f "$1" - then - err "ERROR: No such file: '$1'" - return 1 - fi - - local ui_version=$(sed -n ${SED_EXT} -e 's/.*CONSUL_VERSION%22%3A%22([^%]*)%22%2C%22.*/\1/p' < "$1") || return 1 - echo "$ui_version" - return 0 - } - function ui_logo_type { - # Arguments: - # $1 - path to index.html - # - # Returns: - # 0 - success - # * -failure - # - # Notes: echoes the 'logo type' to stdout upon success - # the 'logo' can be one of 'enterprise' or 'oss' - # and doesn't necessarily correspond to the binary type of consul - # the logo is 'enterprise' if the binary type is anything but 'oss' - if ! test -f "$1" - then - err "ERROR: No such file: '$1'" - return 1 - fi - grep -q "data-enterprise-logo" < "$1" - - if test $? -eq 0 - then - echo "enterprise" - else - echo "oss" - fi - return 0 - } + # Arguments: + # $1 - Path to directory containing the files to shasum + # $2 - File to output sha sums to + # + # Returns: + # 0 - success + # * - failure + + if ! test -d "$1"; then + err "ERROR: '$1' is not a directory and shasum_release requires passing a directory as the first argument" + return 1 + fi + + if test -z "$2"; then + err "ERROR: shasum_release requires a second argument to be the filename to output the shasums to but none was given" + return 1 + fi + + pushd $1 >/dev/null + shasum -a256 * >"$2" + ret=$? + popd >/dev/null + + return $ret +} + +function ui_version { + # Arguments: + # $1 - path to index.html + # + # Returns: + # 0 - success + # * -failure + # + # Notes: echoes the version to stdout upon success + if ! test -f "$1"; then + err "ERROR: No such file: '$1'" + return 1 + fi + + local ui_version=$(sed -n ${SED_EXT} -e 's/.*CONSUL_VERSION%22%3A%22([^%]*)%22%2C%22.*/\1/p' <"$1") || return 1 + echo "$ui_version" + return 0 +} +function ui_logo_type { + # Arguments: + # $1 - path to index.html + # + # Returns: + # 0 - success + # * -failure + # + # Notes: echoes the 'logo type' to stdout upon success + # the 'logo' can be one of 'enterprise' or 'oss' + # and doesn't necessarily correspond to the binary type of consul + # the logo is 'enterprise' if the binary type is anything but 'oss' + if ! test -f "$1"; then + err "ERROR: No such file: '$1'" + return 1 + fi + grep -q "data-enterprise-logo" <"$1" + + if test $? -eq 0; then + echo "enterprise" + else + echo "oss" + fi + return 0 +} diff --git a/control-plane/build-support/scripts/consul-version.sh b/control-plane/build-support/scripts/consul-version.sh index 634b5db07d..e245e2a239 100755 --- a/control-plane/build-support/scripts/consul-version.sh +++ b/control-plane/build-support/scripts/consul-version.sh @@ -4,5 +4,4 @@ FILE=$1 VERSION=$(yq .global.image $FILE) -# echo full string "hashicorp/consul:1.15.1" | remove first and last characters | cut everything before ':' -echo "${VERSION}" | sed 's/^.//;s/.$//' | cut -d ':' -f2- +echo "${VERSION}" From 51967756cbba989796c6473fd3a89dc19956c4be Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Tue, 30 May 2023 15:12:55 -0400 Subject: [PATCH 233/235] backport of commit 08a2cd3399926f3df6177080986892e40333d9ef (#2206) Co-authored-by: DanStough --- .changelog/2204.txt | 3 +++ .github/workflows/build.yml | 2 +- control-plane/Dockerfile | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 .changelog/2204.txt diff --git a/.changelog/2204.txt b/.changelog/2204.txt new file mode 100644 index 0000000000..6962f485a0 --- /dev/null +++ b/.changelog/2204.txt @@ -0,0 +1,3 @@ +```release-note:security +Bump Dockerfile base image for RedHat UBI `consul-k8s-control-plane` image to `ubi-minimal:9.2`. +``` diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c6b107e141..a99179b26e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -162,7 +162,7 @@ jobs: if: ${{ matrix.goos == 'linux' && matrix.component == 'cli' && matrix.goarch == 'amd64'}} uses: addnab/docker-run-action@v3 with: - image: registry.access.redhat.com/ubi8/ubi:latest + image: registry.access.redhat.com/ubi9/ubi:latest options: -v ${{ github.workspace }}:/work run: | dnf install -qy openssl diff --git a/control-plane/Dockerfile b/control-plane/Dockerfile index 8d23426673..311dff9e0a 100644 --- a/control-plane/Dockerfile +++ b/control-plane/Dockerfile @@ -111,7 +111,7 @@ CMD /bin/${BIN_NAME} # We don't rebuild the software because we want the exact checksums and # binary signatures to match the software and our builds aren't fully # reproducible currently. -FROM registry.access.redhat.com/ubi9-minimal:9.1.0 as ubi +FROM registry.access.redhat.com/ubi9-minimal:9.2 as ubi ARG PRODUCT_NAME ARG PRODUCT_VERSION From 6b19b3432a6b7109110dbf34c21d4424e5fd9ac8 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Wed, 31 May 2023 11:24:28 -0400 Subject: [PATCH 234/235] backport of commit 5bb00ebf0fcc3e4dfdb65404db66fcded8f02a84 (#2219) Co-authored-by: Eric --- .changelog/2194.txt | 3 + .../api/v1alpha1/serviceintentions_types.go | 19 ++++- .../v1alpha1/serviceintentions_types_test.go | 72 +++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 .changelog/2194.txt diff --git a/.changelog/2194.txt b/.changelog/2194.txt new file mode 100644 index 0000000000..997326218b --- /dev/null +++ b/.changelog/2194.txt @@ -0,0 +1,3 @@ +```release-note: +crd: fix bug on service intentions CRD causing some updates to be ignored. +``` diff --git a/control-plane/api/v1alpha1/serviceintentions_types.go b/control-plane/api/v1alpha1/serviceintentions_types.go index a0a240639a..1a41caa289 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types.go +++ b/control-plane/api/v1alpha1/serviceintentions_types.go @@ -228,18 +228,34 @@ func (in *ServiceIntentions) ConsulGlobalResource() bool { return false } +func normalizeEmptyToDefault(value string) string { + if value == "" { + return "default" + } + return value +} + func (in *ServiceIntentions) MatchesConsul(candidate api.ConfigEntry) bool { configEntry, ok := candidate.(*capi.ServiceIntentionsConfigEntry) if !ok { return false } + specialEquality := cmp.Options{ + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Sources.Namespace" + }, cmp.Transformer("NormalizeNamespace", normalizeEmptyToDefault)), + cmp.FilterPath(func(path cmp.Path) bool { + return path.String() == "Sources.Partition" + }, cmp.Transformer("NormalizePartition", normalizeEmptyToDefault)), + } + // No datacenter is passed to ToConsul as we ignore the Meta field when checking for equality. return cmp.Equal( in.ToConsul(""), configEntry, cmpopts.IgnoreFields(capi.ServiceIntentionsConfigEntry{}, "Partition", "Namespace", "Meta", "ModifyIndex", "CreateIndex"), - cmpopts.IgnoreFields(capi.SourceIntention{}, "Partition", "Namespace", "LegacyID", "LegacyMeta", "LegacyCreateTime", "LegacyUpdateTime", "Precedence", "Type"), + cmpopts.IgnoreFields(capi.SourceIntention{}, "LegacyID", "LegacyMeta", "LegacyCreateTime", "LegacyUpdateTime", "Precedence", "Type"), cmpopts.IgnoreUnexported(), cmpopts.EquateEmpty(), // Consul will sort the sources by precedence when returning the resource @@ -249,6 +265,7 @@ func (in *ServiceIntentions) MatchesConsul(candidate api.ConfigEntry) bool { // piggyback on strings.Compare that returns -1 if a < b. return strings.Compare(sourceIntentionSortKey(a), sourceIntentionSortKey(b)) == -1 }), + specialEquality, ) } diff --git a/control-plane/api/v1alpha1/serviceintentions_types_test.go b/control-plane/api/v1alpha1/serviceintentions_types_test.go index f9be4120f2..01199f74d1 100644 --- a/control-plane/api/v1alpha1/serviceintentions_types_test.go +++ b/control-plane/api/v1alpha1/serviceintentions_types_test.go @@ -37,6 +37,78 @@ func TestServiceIntentions_MatchesConsul(t *testing.T) { }, Matches: true, }, + "namespaces and partitions equate `default` and empty strings": { + Ours: ServiceIntentions{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + }, + Spec: ServiceIntentionsSpec{ + Destination: IntentionDestination{ + Name: "svc-name", + Namespace: "ns1", + }, + Sources: []*SourceIntention{ + { + Name: "svc1", + Namespace: "", + Partition: "default", + Action: "allow", + }, + }, + }, + }, + Theirs: &capi.ServiceIntentionsConfigEntry{ + Kind: capi.ServiceIntentions, + Name: "svc-name", + Namespace: "ns1", + Sources: []*capi.SourceIntention{ + { + Name: "svc1", + Namespace: "default", + Partition: "", + Action: "allow", + Precedence: 0, + }, + }, + }, + Matches: true, + }, + "source namespaces and partitions are compared": { + Ours: ServiceIntentions{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + }, + Spec: ServiceIntentionsSpec{ + Destination: IntentionDestination{ + Name: "svc-name", + Namespace: "test", + }, + Sources: []*SourceIntention{ + { + Name: "svc1", + Namespace: "test", + Partition: "test", + Action: "allow", + }, + }, + }, + }, + Theirs: &capi.ServiceIntentionsConfigEntry{ + Kind: capi.ServiceIntentions, + Name: "svc-name", + Namespace: "test", + Sources: []*capi.SourceIntention{ + { + Name: "svc1", + Namespace: "not-test", + Partition: "not-test", + Action: "allow", + Precedence: 0, + }, + }, + }, + Matches: false, + }, "all fields set matches": { Ours: ServiceIntentions{ ObjectMeta: metav1.ObjectMeta{ From 3ef7e4e5bae676ba8f3cfe2bfd7cb1a107447030 Mon Sep 17 00:00:00 2001 From: hc-github-team-consul-core Date: Thu, 1 Jun 2023 10:35:36 -0400 Subject: [PATCH 235/235] backport of commit 71293afebc6624d73bb05a51c34bc93ccc925dc3 (#2234) Co-authored-by: Curt Bushko --- Makefile | 5 +++++ .../build-support/scripts/consul-dataplane-version.sh | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100755 control-plane/build-support/scripts/consul-dataplane-version.sh diff --git a/Makefile b/Makefile index c6e060a7de..f7f9e3434a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ VERSION = $(shell ./control-plane/build-support/scripts/version.sh control-plane/version/version.go) CONSUL_IMAGE_VERSION = $(shell ./control-plane/build-support/scripts/consul-version.sh charts/consul/values.yaml) +CONSUL_DATAPLANE_IMAGE_VERSION = $(shell ./control-plane/build-support/scripts/consul-dataplane-version.sh charts/consul/values.yaml) # ===========> Helm Targets @@ -151,6 +152,10 @@ version: consul-version: @echo $(CONSUL_IMAGE_VERSION) +consul-dataplane-version: + @echo $(CONSUL_DATAPLANE_IMAGE_VERSION) + + # ===========> Release Targets prepare-release: ## Sets the versions, updates changelog to prepare this repository to release diff --git a/control-plane/build-support/scripts/consul-dataplane-version.sh b/control-plane/build-support/scripts/consul-dataplane-version.sh new file mode 100755 index 0000000000..906ee54a1f --- /dev/null +++ b/control-plane/build-support/scripts/consul-dataplane-version.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 +FILE=$1 +VERSION=$(yq .global.imageConsulDataplane $FILE) + +echo "${VERSION}"