diff --git a/vendor/knative.dev/pkg/test/README.md b/vendor/knative.dev/pkg/test/README.md deleted file mode 100644 index d54c9ae27..000000000 --- a/vendor/knative.dev/pkg/test/README.md +++ /dev/null @@ -1,218 +0,0 @@ -# Test - -This directory contains tests and testing docs. - -- [Test library](#test-library) contains code you can use in your `knative` - tests -- [Flags](#flags) added by [the test library](#test-library) -- [Unit tests](#running-unit-tests) currently reside in the codebase alongside - the code they test - -## Running unit tests - -To run all unit tests: - -```bash -go test ./... -``` - -## Test library - -You can use the test library in this dir to: - -- [Use common test flags](#use-common-test-flags) -- [Output logs](#output-logs) -- [Ensure test cleanup](#ensure-test-cleanup) - -### Use common test flags - -These flags are useful for running against an existing cluster, making use of -your existing -[environment setup](https://github.com/knative/serving/blob/main/DEVELOPMENT.md#environment-setup). - -By importing `knative.dev/pkg/test` you get access to a global variable called -`test.Flags` which holds the values of -[the command line flags](/test/README.md#flags). - -```go -logger.Infof("Using namespace %s", test.Flags.Namespace) -``` - -_See [e2e_flags.go](./e2e_flags.go)._ - -### Output logs - -[When tests are run with `--logverbose` option](README.md#output-verbose-logs), -debug logs will be emitted to stdout. - -We are using a generic -[FormatLogger](https://github.com/knative/pkg/blob/main/test/logging/logging.go#L49) -that can be passed in any existing logger that satisfies it. Test can use the -generic [logging methods](https://golang.org/pkg/testing/#T) to log info and -error logs. All the common methods accept generic FormatLogger as a parameter -and tests can pass in `t.Logf` like this: - -```go -_, err = pkgTest.WaitForEndpointState( - kubeClient, - t.Logf, - ...), -``` - -_See [logging.go](./logging/logging.go)._ - -### Check Knative Serving resources - -_WARNING: this code also exists in -[`knative/serving`](https://github.com/knative/serving/blob/main/test/adding_tests.md#make-requests-against-deployed-services)._ - -After creating Knative Serving resources or making changes to them, you will -need to wait for the system to realize those changes. You can use the Knative -Serving CRD check and polling methods to check the resources are either in or -reach the desired state. - -The `WaitFor*` functions use the kubernetes -[`wait` package](https://godoc.org/k8s.io/apimachinery/pkg/util/wait). To poll -they use -[`PollImmediate`](https://godoc.org/k8s.io/apimachinery/pkg/util/wait#PollImmediate) -and the return values of the function you provide behave the same as -[`ConditionFunc`](https://godoc.org/k8s.io/apimachinery/pkg/util/wait#ConditionFunc): -a `bool` to indicate if the function should stop or continue polling, and an -`error` to indicate if there has been an error. - -For example, you can poll a `Configuration` object to find the name of the -`Revision` that was created for it: - -```go -var revisionName string -err := test.WaitForConfigurationState( - clients.ServingClient, configName, func(c *v1alpha1.Configuration) (bool, error) { - if c.Status.LatestCreatedRevisionName != "" { - revisionName = c.Status.LatestCreatedRevisionName - return true, nil - } - return false, nil - }, "ConfigurationUpdatedWithRevision") -``` - -_See [kube_checks.go](./kube_checks.go)._ - -### Ensure test cleanup - -To ensure your test is cleaned up, you should defer cleanup to execute after -your test completes and also ensure the cleanup occurs if the test is -interrupted: - -```go -defer tearDown(clients) -test.CleanupOnInterrupt(func() { tearDown(clients) }) -``` - -_See [cleanup.go](./cleanup.go)._ - -## Flags - -Importing [the test library](#test-library) adds flags that are useful for end -to end tests that need to run against a cluster. - -Tests importing [`knative.dev/pkg/test`](#test-library) recognize these flags: - -- [`--kubeconfig`](#specifying-kubeconfig) -- [`--cluster`](#specifying-cluster) -- [`--namespace`](#specifying-namespace) -- [`--logverbose`](#output-verbose-logs) -- [`--ingressendpoint`](#specifying-ingress-endpoint) -- [`--dockerrepo`](#specifying-docker-repo) -- [`--tag`](#specifying-tag) -- [`--imagetemplate`](#specifying-image-template) - -### Specifying kubeconfig - -By default the tests will use the -[kubeconfig file](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/) -at `~/.kube/config`. If there is an error getting the current user, it will use -`kubeconfig` instead as the default value. You can specify a different config -file with the argument `--kubeconfig`. - -To run tests with a non-default kubeconfig file: - -```bash -go test ./test --kubeconfig /my/path/kubeconfig -``` - -### Specifying cluster - -The `--cluster` argument lets you use a different cluster than -[your specified kubeconfig's](#specifying-kubeconfig) active context. - -```bash -go test ./test --cluster your-cluster-name -``` - -The current cluster names can be obtained by running: - -```bash -kubectl config get-clusters -``` - -### Specifying ingress endpoint - -The `--ingressendpoint` argument lets you specify a static url to use as the -ingress server during tests. This is useful for Kubernetes configurations which -do not provide external IPs. - -```bash -go test ./test --ingressendpoint :32380 -``` - -### Specifying namespace - -The `--namespace` argument lets you specify the namespace to use for the tests. -By default, tests will use `serving-tests`. - -```bash -go test ./test --namespace your-namespace-name -``` - -### Output verbose logs - -The `--logverbose` argument lets you see verbose test logs and k8s logs. - -```bash -go test ./test --logverbose -``` - -### Specifying docker repo - -The `--dockerrepo` argument lets you specify a uri of the docker repo where you -have uploaded the test image to using `uploadtestimage.sh`. Defaults to -`$KO_DOCKER_REPO` - -```bash -go test ./test --dockerrepo myspecialdockerrepo -``` - -### Specifying tag - -The `--tag` argument lets you specify the version tag for the test images. - -```bash -go test ./test --tag v1.0 -``` - -### Specifying image template - -The `--imagetemplate` argument lets you specify a template to generate the -reference to an image from the test. Defaults to -`{{.Repository}}/{{.Name}}:{{.Tag}}` - -```bash -go test ./test --imagetemplate {{.Repository}}/{{.Name}}:{{.Tag}} -``` - ---- - -Except as otherwise noted, the content of this page is licensed under the -[Creative Commons Attribution 4.0 License](https://creativecommons.org/licenses/by/4.0/), -and code samples are licensed under the -[Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0). diff --git a/vendor/knative.dev/pkg/test/cleanup.go b/vendor/knative.dev/pkg/test/cleanup.go deleted file mode 100644 index 7fc91bc5e..000000000 --- a/vendor/knative.dev/pkg/test/cleanup.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2018 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package test - -import ( - "os" - "os/signal" - "sync" -) - -type logFunc func(template string, args ...interface{}) - -var cleanup struct { - once sync.Once - mutex sync.RWMutex - funcs []func() -} - -func waitForInterrupt() { - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - - go func() { - <-c - - cleanup.mutex.RLock() - defer cleanup.mutex.RUnlock() - - for i := len(cleanup.funcs) - 1; i >= 0; i-- { - cleanup.funcs[i]() - } - - os.Exit(1) - }() -} - -// CleanupOnInterrupt will execute the function if an interrupt signal is caught -// Deprecated - use OnInterrupt -func CleanupOnInterrupt(f func(), log logFunc) { - OnInterrupt(f) -} - -// OnInterrupt registers a cleanup function to run if an interrupt signal is caught -func OnInterrupt(cleanupFunc func()) { - cleanup.once.Do(waitForInterrupt) - - cleanup.mutex.Lock() - defer cleanup.mutex.Unlock() - - cleanup.funcs = append(cleanup.funcs, cleanupFunc) -} diff --git a/vendor/knative.dev/pkg/test/clients.go b/vendor/knative.dev/pkg/test/clients.go deleted file mode 100644 index 88530c36b..000000000 --- a/vendor/knative.dev/pkg/test/clients.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2018 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This file contains an object which encapsulates k8s clients which are useful for e2e tests. - -package test - -import ( - "context" - "fmt" - "strings" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - "knative.dev/pkg/test/logging" - "knative.dev/pkg/test/spoof" -) - -// NewSpoofingClient returns a spoofing client to make requests -func NewSpoofingClient(ctx context.Context, client kubernetes.Interface, logf logging.FormatLogger, - domain string, resolvable bool, opts ...spoof.TransportOption) (*spoof.SpoofingClient, error) { - return spoof.New(ctx, client, logf, domain, resolvable, Flags.IngressEndpoint, - Flags.SpoofRequestInterval, Flags.SpoofRequestTimeout, opts...) -} - -// BuildClientConfig builds the client config specified by the config path and the cluster name -func BuildClientConfig(kubeConfigPath string, clusterName string) (*rest.Config, error) { - loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() - overrides := clientcmd.ConfigOverrides{} - - if kubeConfigPath != "" { - loadingRules.ExplicitPath = kubeConfigPath - } - // Override the cluster name if provided. - if clusterName != "" { - overrides.Context.Cluster = clusterName - } - return clientcmd.NewNonInteractiveDeferredLoadingClientConfig( - loadingRules, - &overrides).ClientConfig() -} - -// UpdateConfigMap updates the config map for specified @name with values -func UpdateConfigMap(ctx context.Context, client kubernetes.Interface, name string, configName string, values map[string]string) error { - configMap, err := client.CoreV1().ConfigMaps(name).Get(ctx, configName, metav1.GetOptions{}) - if err != nil { - return err - } - - for key, value := range values { - configMap.Data[key] = value - } - - _, err = client.CoreV1().ConfigMaps(name).Update(ctx, configMap, metav1.UpdateOptions{}) - return err -} - -// CreatePod will create a Pod -func CreatePod(ctx context.Context, client kubernetes.Interface, pod *corev1.Pod) (*corev1.Pod, error) { - pods := client.CoreV1().Pods(pod.GetNamespace()) - return pods.Create(ctx, pod, metav1.CreateOptions{}) -} - -// PodLogs returns Pod logs for given Pod and Container in the namespace -func PodLogs(ctx context.Context, client kubernetes.Interface, podName, containerName, namespace string) ([]byte, error) { - pods := client.CoreV1().Pods(namespace) - podList, err := pods.List(ctx, metav1.ListOptions{}) - if err != nil { - return nil, err - } - for i := range podList.Items { - // Pods are big, so avoid copying. - pod := &podList.Items[i] - if strings.Contains(pod.Name, podName) { - result := pods.GetLogs(pod.Name, &corev1.PodLogOptions{ - Container: containerName, - }).Do(ctx) - return result.Raw() - } - } - return nil, fmt.Errorf("could not find logs for %s/%s:%s", namespace, podName, containerName) -} diff --git a/vendor/knative.dev/pkg/test/crd.go b/vendor/knative.dev/pkg/test/crd.go deleted file mode 100644 index eb7c0e0b3..000000000 --- a/vendor/knative.dev/pkg/test/crd.go +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This file contains functions that construct boilerplate CRD definitions. - -package test - -import ( - corev1 "k8s.io/api/core/v1" - rbacv1 "k8s.io/api/rbac/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -const ( - nginxPort = 80 - nginxName = "nginx" - nginxImage = "nginx:1.7.9" -) - -// ServiceAccount returns ServiceAccount object in given namespace -func ServiceAccount(name, namespace string) *corev1.ServiceAccount { - return &corev1.ServiceAccount{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - } -} - -// ClusterRoleBinding returns ClusterRoleBinding for given subject and role -func ClusterRoleBinding(name string, namespace string, serviceAccount string, role string) *rbacv1.ClusterRoleBinding { - return &rbacv1.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Subjects: []rbacv1.Subject{ - { - Kind: "ServiceAccount", - Name: serviceAccount, - Namespace: namespace, - }, - }, - RoleRef: rbacv1.RoleRef{ - Kind: "ClusterRole", - Name: role, - APIGroup: "rbac.authorization.k8s.io", - }, - } -} - -// CoreV1ObjectReference returns a corev1.ObjectReference for the given name, kind and apiversion -func CoreV1ObjectReference(kind, apiversion, name string) *corev1.ObjectReference { - return &corev1.ObjectReference{ - Kind: kind, - APIVersion: apiversion, - Name: name, - } -} - -// NginxPod returns nginx pod defined in given namespace -func NginxPod(namespace string) *corev1.Pod { - return &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: nginxName, - Namespace: namespace, - Annotations: map[string]string{"sidecar.istio.io/inject": "true"}, - }, - Spec: corev1.PodSpec{ - Containers: []corev1.Container{ - { - Name: nginxName, - Image: nginxImage, - Ports: []corev1.ContainerPort{ - { - ContainerPort: nginxPort, - }, - }, - }, - }, - }, - } -} diff --git a/vendor/knative.dev/pkg/test/e2e_flags.go b/vendor/knative.dev/pkg/test/e2e_flags.go deleted file mode 100644 index ef9b5519e..000000000 --- a/vendor/knative.dev/pkg/test/e2e_flags.go +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright 2018 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This file contains logic to encapsulate flags which are needed to specify -// what cluster, etc. to use for e2e tests. - -package test - -import ( - "bytes" - "flag" - "text/template" - - env "knative.dev/pkg/environment" - testenv "knative.dev/pkg/test/environment" - "knative.dev/pkg/test/logging" -) - -var ( - // Flags holds the command line flags or defaults for settings in the user's environment. - // See EnvironmentFlags for a list of supported fields. - // Deprecated: use test/flags.Flags() - Flags = initializeFlags() -) - -// EnvironmentFlags define the flags that are needed to run the e2e tests. -// Deprecated: use test/flags.Flags() or injection.Flags() -type EnvironmentFlags struct { - env.ClientConfig - testenv.TestClientConfig -} - -func initializeFlags() *EnvironmentFlags { - f := new(EnvironmentFlags) - - f.ClientConfig.InitFlags(flag.CommandLine) - f.TestClientConfig.InitFlags(flag.CommandLine) - - return f -} - -// SetupLoggingFlags initializes a logger for tests. -// TODO(coryrc): Remove once other repos are moved to call logging.InitializeLogger() directly -func SetupLoggingFlags() { - logging.InitializeLogger() -} - -// ImagePath is a helper function to transform an image name into an image reference that can be pulled. -func ImagePath(name string) string { - tpl, err := template.New("image").Parse(Flags.ImageTemplate) - if err != nil { - panic("could not parse image template: " + err.Error()) - } - - var buf bytes.Buffer - if err := tpl.Execute(&buf, struct { - Repository string - Name string - Tag string - }{ - Repository: Flags.DockerRepo, - Name: name, - Tag: Flags.Tag, - }); err != nil { - panic("could not apply the image template: " + err.Error()) - } - return buf.String() -} diff --git a/vendor/knative.dev/pkg/test/environment/config.go b/vendor/knative.dev/pkg/test/environment/config.go deleted file mode 100644 index 6591a4637..000000000 --- a/vendor/knative.dev/pkg/test/environment/config.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2020 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// This file contains logic to encapsulate flags which are needed to specify -// what cluster, etc. to use for e2e tests. - -package environment - -import ( - "flag" - "os" - "time" -) - -// TestClientConfig defines propertis about the test environment -type TestClientConfig struct { - Namespace string // K8s namespace (blank by default, to be overwritten by test suite) - IngressEndpoint string // Host to use for ingress endpoint - ImageTemplate string // Template to build the image reference (defaults to {{.Repository}}/{{.Name}}:{{.Tag}}) - DockerRepo string // Docker repo (defaults to $KO_DOCKER_REPO) - Tag string // Tag for test images - SpoofRequestInterval time.Duration // SpoofRequestInterval is the interval between requests in SpoofingClient - SpoofRequestTimeout time.Duration // SpoofRequestTimeout is the timeout for polling requests in SpoofingClient -} - -// InitFlags is for explicitly initializing the flags. -func (c *TestClientConfig) InitFlags(fs *flag.FlagSet) { - fs.StringVar(&c.Namespace, "namespace", "", - "Provide the namespace you would like to use for these tests.") - - fs.StringVar(&c.IngressEndpoint, "ingressendpoint", "", "Provide a static endpoint url to the ingress server used during tests.") - - fs.StringVar(&c.ImageTemplate, "imagetemplate", "{{.Repository}}/{{.Name}}:{{.Tag}}", - "Provide a template to generate the reference to an image from the test. Defaults to `{{.Repository}}/{{.Name}}:{{.Tag}}`.") - - fs.DurationVar(&c.SpoofRequestInterval, "spoofinterval", 1*time.Second, - "Provide an interval between requests for the SpoofingClient") - - fs.DurationVar(&c.SpoofRequestTimeout, "spooftimeout", 5*time.Minute, - "Provide a request timeout for the SpoofingClient") - - defaultRepo := os.Getenv("KO_DOCKER_REPO") - fs.StringVar(&c.DockerRepo, "dockerrepo", defaultRepo, - "Provide the uri of the docker repo you have uploaded the test image to using `uploadtestimage.sh`. Defaults to $KO_DOCKER_REPO") - - fs.StringVar(&c.Tag, "tag", "latest", "Provide the version tag for the test images.") -} diff --git a/vendor/knative.dev/pkg/test/ingress/ingress.go b/vendor/knative.dev/pkg/test/ingress/ingress.go deleted file mode 100644 index 8de4052c7..000000000 --- a/vendor/knative.dev/pkg/test/ingress/ingress.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ingress - -import ( - "context" - "fmt" - "os" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" -) - -const ( - // TODO(tcnghia): These probably shouldn't be hard-coded here? - istioIngressNamespace = "istio-system" - istioIngressName = "istio-ingressgateway" -) - -// GetIngressEndpoint gets the ingress public IP or hostname. -// address - is the endpoint to which we should actually connect. -// portMap - translates the request's port to the port on address to which the caller -// -// should connect. This is used when the resolution to address goes through some -// sort of port-mapping, e.g. Kubernetes node ports. -// -// err - an error when address/portMap cannot be established. -func GetIngressEndpoint(ctx context.Context, kubeClientset kubernetes.Interface, endpointOverride string) (address string, portMap func(string) string, err error) { - ingressName := istioIngressName - if gatewayOverride := os.Getenv("GATEWAY_OVERRIDE"); gatewayOverride != "" { - ingressName = gatewayOverride - } - ingressNamespace := istioIngressNamespace - if gatewayNsOverride := os.Getenv("GATEWAY_NAMESPACE_OVERRIDE"); gatewayNsOverride != "" { - ingressNamespace = gatewayNsOverride - } - - ingress, err := kubeClientset.CoreV1().Services(ingressNamespace).Get(ctx, ingressName, metav1.GetOptions{}) - if err != nil { - return "", nil, err - } - - // If an override is provided, use it - if endpointOverride != "" { - return endpointOverride, func(port string) string { - for _, sp := range ingress.Spec.Ports { - if fmt.Sprint(sp.Port) == port { - return fmt.Sprint(sp.NodePort) - } - } - return port - }, nil - } - endpoint, err := EndpointFromService(ingress) - if err != nil { - return "", nil, err - } - return endpoint, func(in string) string { return in }, nil -} - -// EndpointFromService extracts the endpoint from the service's ingress. -func EndpointFromService(svc *v1.Service) (string, error) { - ingresses := svc.Status.LoadBalancer.Ingress - if len(ingresses) != 1 { - return "", fmt.Errorf("expected exactly one ingress load balancer, instead had %d: %v", len(ingresses), ingresses) - } - itu := ingresses[0] - - switch { - case itu.IP != "": - return itu.IP, nil - case itu.Hostname != "": - return itu.Hostname, nil - default: - return "", fmt.Errorf("expected ingress loadbalancer IP or hostname for %s to be set, instead was empty", svc.Name) - } -} diff --git a/vendor/knative.dev/pkg/test/kube_checks.go b/vendor/knative.dev/pkg/test/kube_checks.go deleted file mode 100644 index 3e295a55f..000000000 --- a/vendor/knative.dev/pkg/test/kube_checks.go +++ /dev/null @@ -1,282 +0,0 @@ -/* -Copyright 2018 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// kube_checks contains functions which poll Kubernetes objects until -// they get into the state desired by the caller or time out. - -package test - -import ( - "context" - "fmt" - "strings" - "time" - - "github.com/davecgh/go-spew/spew" - "github.com/google/go-cmp/cmp" - appsv1 "k8s.io/api/apps/v1" - corev1 "k8s.io/api/core/v1" - apierrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - k8styped "k8s.io/client-go/kubernetes/typed/core/v1" - - "knative.dev/pkg/test/logging" -) - -const ( - interval = 1 * time.Second - podTimeout = 8 * time.Minute - logTimeout = 1 * time.Minute -) - -// WaitForDeploymentState polls the status of the Deployment called name -// from client every interval until inState returns `true` indicating it -// is done, returns an error or timeout. desc will be used to name the metric -// that is emitted to track how long it took for name to get into the state checked by inState. -func WaitForDeploymentState(ctx context.Context, client kubernetes.Interface, name string, inState func(d *appsv1.Deployment) (bool, error), desc string, namespace string, timeout time.Duration) error { - d := client.AppsV1().Deployments(namespace) - span := logging.GetEmitableSpan(ctx, fmt.Sprintf("WaitForDeploymentState/%s/%s", name, desc)) - defer span.End() - var lastState *appsv1.Deployment - waitErr := wait.PollImmediate(interval, timeout, func() (bool, error) { - var err error - lastState, err = d.Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return true, err - } - return inState(lastState) - }) - - if waitErr != nil { - return fmt.Errorf("deployment %q is not in desired state, got: %s: %w", name, spew.Sprint(lastState), waitErr) - } - return nil -} - -// WaitForPodListState polls the status of the PodList -// from client every interval until inState returns `true` indicating it -// is done, returns an error or timeout. desc will be used to name the metric -// that is emitted to track how long it took to get into the state checked by inState. -func WaitForPodListState(ctx context.Context, client kubernetes.Interface, inState func(p *corev1.PodList) (bool, error), desc string, namespace string) error { - p := client.CoreV1().Pods(namespace) - span := logging.GetEmitableSpan(ctx, "WaitForPodListState/"+desc) - defer span.End() - - var lastState *corev1.PodList - waitErr := wait.PollImmediate(interval, podTimeout, func() (bool, error) { - var err error - lastState, err = p.List(ctx, metav1.ListOptions{}) - if err != nil { - return true, err - } - return inState(lastState) - }) - - if waitErr != nil { - return fmt.Errorf("pod list is not in desired state, got: %s: %w", spew.Sprint(lastState), waitErr) - } - return nil -} - -// WaitForPodState polls the status of the specified Pod -// from client every interval until inState returns `true` indicating it -// is done, returns an error or timeout. desc will be used to name the metric -// that is emitted to track how long it took to get into the state checked by inState. -func WaitForPodState(ctx context.Context, client kubernetes.Interface, inState func(p *corev1.Pod) (bool, error), name string, namespace string) error { - p := client.CoreV1().Pods(namespace) - span := logging.GetEmitableSpan(ctx, "WaitForPodState/"+name) - defer span.End() - - var lastState *corev1.Pod - waitErr := wait.PollImmediate(interval, podTimeout, func() (bool, error) { - var err error - lastState, err = p.Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return false, err - } - return inState(lastState) - }) - - if waitErr != nil { - return fmt.Errorf("pod %q is not in desired state, got: %s: %w", name, spew.Sprint(lastState), waitErr) - } - return nil -} - -// WaitForPodDeleted waits for the given pod to disappear from the given namespace. -func WaitForPodDeleted(ctx context.Context, client kubernetes.Interface, name, namespace string) error { - if err := WaitForPodState(ctx, client, func(p *corev1.Pod) (bool, error) { - // Always return false. We're oly interested in the error which indicates pod deletion or timeout. - return false, nil - }, name, namespace); err != nil { - if !apierrs.IsNotFound(err) { - return err - } - } - return nil -} - -// WaitForServiceEndpoints polls the status of the specified Service -// from client every interval until number of service endpoints = numOfEndpoints -func WaitForServiceEndpoints(ctx context.Context, client kubernetes.Interface, svcName string, svcNamespace string, numOfEndpoints int) error { - endpointsService := client.CoreV1().Endpoints(svcNamespace) - span := logging.GetEmitableSpan(ctx, "WaitForServiceHasAtLeastOneEndpoint/"+svcName) - defer span.End() - - var endpoints *corev1.Endpoints - waitErr := wait.PollImmediate(interval, podTimeout, func() (bool, error) { - var err error - endpoints, err = endpointsService.Get(ctx, svcName, metav1.GetOptions{}) - if apierrs.IsNotFound(err) { - return false, nil - } - if err != nil { - return false, err - } - - return countEndpointsNum(endpoints) == numOfEndpoints, nil - }) - if waitErr != nil { - return fmt.Errorf("did not reach the desired number of endpoints, got: %d: %w", countEndpointsNum(endpoints), waitErr) - } - return nil -} - -func countEndpointsNum(e *corev1.Endpoints) int { - if e == nil || e.Subsets == nil { - return 0 - } - num := 0 - for _, sub := range e.Subsets { - num += len(sub.Addresses) - } - return num -} - -// GetEndpointAddresses returns addresses of endpoints for the given service. -func GetEndpointAddresses(ctx context.Context, client kubernetes.Interface, svcName, svcNamespace string) ([]string, error) { - endpoints, err := client.CoreV1().Endpoints(svcNamespace).Get(ctx, svcName, metav1.GetOptions{}) - if err != nil || countEndpointsNum(endpoints) == 0 { - return nil, fmt.Errorf("no endpoints or error: %w", err) - } - var hosts []string - for _, sub := range endpoints.Subsets { - for _, addr := range sub.Addresses { - hosts = append(hosts, addr.IP) - } - } - return hosts, nil -} - -// WaitForChangedEndpoints waits until the endpoints for the given service differ from origEndpoints. -func WaitForChangedEndpoints(ctx context.Context, client kubernetes.Interface, svcName, svcNamespace string, origEndpoints []string) error { - var newEndpoints []string - waitErr := wait.PollImmediate(1*time.Second, 2*time.Minute, func() (bool, error) { - var err error - newEndpoints, err = GetEndpointAddresses(ctx, client, svcName, svcNamespace) - return !cmp.Equal(origEndpoints, newEndpoints), err - }) - if waitErr != nil { - return fmt.Errorf("new endpoints are not different from the original ones, got %q: %w", newEndpoints, waitErr) - } - return nil -} - -// GetConfigMap gets the configmaps for a given namespace -func GetConfigMap(client kubernetes.Interface, namespace string) k8styped.ConfigMapInterface { - return client.CoreV1().ConfigMaps(namespace) -} - -// DeploymentScaledToZeroFunc returns a func that evaluates if a deployment has scaled to 0 pods -func DeploymentScaledToZeroFunc() func(d *appsv1.Deployment) (bool, error) { - return func(d *appsv1.Deployment) (bool, error) { - return d.Status.ReadyReplicas == 0, nil - } -} - -// WaitForLogContent waits until logs for given Pod/Container include the given content. -// If the content is not present within timeout it returns error. -func WaitForLogContent(ctx context.Context, client kubernetes.Interface, podName, containerName, namespace, content string) error { - var logs []byte - waitErr := wait.PollImmediate(interval, logTimeout, func() (bool, error) { - var err error - logs, err = PodLogs(ctx, client, podName, containerName, namespace) - if err != nil { - return true, err - } - return strings.Contains(string(logs), content), nil - }) - if waitErr != nil { - return fmt.Errorf("logs do not contain the desired content %q, got %q: %w", content, logs, waitErr) - } - return nil -} - -// WaitForAllPodsRunning waits for all the pods to be in running state -func WaitForAllPodsRunning(ctx context.Context, client kubernetes.Interface, namespace string) error { - return WaitForPodListState(ctx, client, podsRunning, "PodsAreRunning", namespace) -} - -// WaitForPodRunning waits for the given pod to be in running state -func WaitForPodRunning(ctx context.Context, client kubernetes.Interface, name string, namespace string) error { - var p *corev1.Pod - pods := client.CoreV1().Pods(namespace) - waitErr := wait.PollImmediate(interval, podTimeout, func() (bool, error) { - var err error - p, err = pods.Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return true, err - } - return podRunning(p), nil - }) - if waitErr != nil { - return fmt.Errorf("pod %q did not reach the running state, got %+v: %w", name, p.Status.Phase, waitErr) - } - return nil -} - -// podsRunning will check the status conditions of the pod list and return true all pods are Running -func podsRunning(podList *corev1.PodList) (bool, error) { - // Pods are big, so use indexing, to avoid copying. - for i := range podList.Items { - if isRunning := podRunning(&podList.Items[i]); !isRunning { - return false, nil - } - } - return true, nil -} - -// podRunning will check the status conditions of the pod and return true if it's Running. -func podRunning(pod *corev1.Pod) bool { - return pod.Status.Phase == corev1.PodRunning || pod.Status.Phase == corev1.PodSucceeded -} - -// WaitForDeploymentScale waits until the given deployment has the expected scale. -func WaitForDeploymentScale(ctx context.Context, client kubernetes.Interface, name, namespace string, scale int) error { - return WaitForDeploymentState( - ctx, - client, - name, - func(d *appsv1.Deployment) (bool, error) { - return d.Status.ReadyReplicas == int32(scale), nil - }, - "DeploymentIsScaled", - namespace, - time.Minute, - ) -} diff --git a/vendor/knative.dev/pkg/test/logstream/README.md b/vendor/knative.dev/pkg/test/logstream/README.md deleted file mode 100644 index 7c7886bd5..000000000 --- a/vendor/knative.dev/pkg/test/logstream/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# How to use logstream - -This is a guide to start using `logstream` in your e2e testing. - -## Requirements - -1. The `SYSTEM_NAMESPACE` environment variable must be configured. Many of the - knative test scripts already define this, and in some places (e.g. serving) - randomize it. However, to facilitate usage outside of CI, you should consider - including a package like - [this](https://github.com/knative/serving/blob/main/test/defaultsystem/system.go) - and linking it like - [this](https://github.com/knative/serving/blob/e797247322b5aa35001152d2a2715dbc20a86cc4/test/conformance.go#L20-L23) - -2. Test resources must be named with - [`test.ObjectNameForTest(t)`](https://github.com/knative/networking/blob/40ef99aa5db0d38730a89a1de7e5b28b8ef6eed5/vendor/knative.dev/pkg/test/helpers/name.go#L50) - -3. At the start of your test add: `t.Cleanup(logstream.Start(t))` - -4. To enable logcapture from containers across multiple namespaces configure - SYSTEM_NAMESPACE to contains a csv list of namespaces - (`knative-serving,knative-test ??????{}`). Specific, well known containers - that do not produce key decorated logs (see detailed description below) need - to be enumerated in WellKnownContainers in stream.go. - -With that, you will start getting logs from the processes in the system -namespace interleaved into your test output via `t.Log`. - -## How it works - -In Knative we use `zap.Logger` for all of our logging, and most of those loggers -(e.g. in the context of a reconcile) have been decorated with the "key" of the -resource being processed. `logstream` simply decodes these structured log -messages and when the `key` matches the naming prefix that `ObjectNameForTest` -uses, it includes it into the test's output. - -## Integrating in Libraries. - -When a shared component is set up and called from reconciliation, it may have -it's own logger. If that component is dealing with individual resources, it can -scope individual log statements to that resource by decorating the logger with -its key like so: - -``` -logger := logger.With(zap.String(logkey.Key, resourceKey)) -``` - -Now, any log statements that the library prints through this logger will appear -in the logstream! - -For an example of this pattern, see -[the knative/networking prober library](https://github.com/knative/networking/blob/main/pkg/status/status.go). diff --git a/vendor/knative.dev/pkg/test/logstream/doc.go b/vendor/knative.dev/pkg/test/logstream/doc.go deleted file mode 100644 index ddad2c446..000000000 --- a/vendor/knative.dev/pkg/test/logstream/doc.go +++ /dev/null @@ -1,21 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package logstream lets end-to-end tests incorporate controller logs -// into the error output of tests. It is enabled by setting the -// SYSTEM_NAMESPACE environment variable, which tells this package -// what namespace to stream logs from. -package logstream diff --git a/vendor/knative.dev/pkg/test/logstream/interface.go b/vendor/knative.dev/pkg/test/logstream/interface.go deleted file mode 100644 index a1b39aabd..000000000 --- a/vendor/knative.dev/pkg/test/logstream/interface.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package logstream - -import ( - "context" - "fmt" - "os" - "strings" - "sync" - - "k8s.io/client-go/kubernetes" - "knative.dev/pkg/system" - "knative.dev/pkg/test" - "knative.dev/pkg/test/helpers" - logstreamv2 "knative.dev/pkg/test/logstream/v2" -) - -type ( - // Canceler is the type of function returned when a logstream is started to be - // deferred so that the logstream can be stopped when the test is complete. - Canceler = logstreamv2.Canceler -) - -type ti interface { - Name() string - Error(args ...interface{}) - Log(args ...interface{}) - Logf(fmt string, args ...interface{}) -} - -// Start begins streaming the logs from system components with a `key:` matching -// `test.ObjectNameForTest(t)` to `t.Log`. It returns a Canceler, which must -// be called before the test completes. -func Start(t ti) Canceler { - // Do this lazily to make import ordering less important. - once.Do(func() { - if ns := os.Getenv(system.NamespaceEnvKey); ns != "" { - var err error - // handle case when ns contains a csv list - namespaces := strings.Split(ns, ",") - if sysStream, err = initStream(namespaces); err != nil { - t.Error("Error initializing logstream", "error", err) - } - } else { - // Otherwise, set up a null stream. - sysStream = &null{} - } - }) - - return sysStream.Start(t) -} - -func initStream(namespaces []string) (streamer, error) { - config, err := test.Flags.GetRESTConfig() - if err != nil { - return &null{}, fmt.Errorf("error loading client config: %w", err) - } - - kc, err := kubernetes.NewForConfig(config) - if err != nil { - return &null{}, fmt.Errorf("error creating kubernetes client: %w", err) - } - - return &shim{logstreamv2.FromNamespaces(context.Background(), kc, namespaces)}, nil -} - -type streamer interface { - Start(t ti) Canceler -} - -var ( - sysStream streamer - once sync.Once -) - -type shim struct { - logstreamv2.Source -} - -func (s *shim) Start(t ti) Canceler { - name := helpers.ObjectPrefixForTest(t) - canceler, err := s.StartStream(name, t.Logf) - - if err != nil { - t.Error("Failed to start logstream", "error", err) - } - - return canceler -} diff --git a/vendor/knative.dev/pkg/test/logstream/null.go b/vendor/knative.dev/pkg/test/logstream/null.go deleted file mode 100644 index 13697aae4..000000000 --- a/vendor/knative.dev/pkg/test/logstream/null.go +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package logstream - -type null struct{} - -var _ streamer = (*null)(nil) - -// Start implements streamer -func (*null) Start(t ti) Canceler { - t.Log("logstream was requested, but SYSTEM_NAMESPACE was unset.") - return func() {} -} diff --git a/vendor/knative.dev/pkg/test/presubmit-tests.sh b/vendor/knative.dev/pkg/test/presubmit-tests.sh deleted file mode 100644 index e03367a1b..000000000 --- a/vendor/knative.dev/pkg/test/presubmit-tests.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2018 The Knative Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script runs the presubmit tests, in the right order. -# It is started by prow for each PR. -# For convenience, it can also be executed manually. - -export GO111MODULE=on - -source $(dirname $0)/../vendor/knative.dev/hack/presubmit-tests.sh - -# TODO(#17): Write integration tests. - -# We use the default build, unit and integration test runners. - -function pre_build_tests() { - # Test the custom code generators. This makes sure we can compile the output - # of the injection generators. - $(dirname $0)/test-reconciler-codegen.sh - return 0 -} - -main $@ diff --git a/vendor/knative.dev/pkg/test/request.go b/vendor/knative.dev/pkg/test/request.go deleted file mode 100644 index a22542e29..000000000 --- a/vendor/knative.dev/pkg/test/request.go +++ /dev/null @@ -1,160 +0,0 @@ -/* -Copyright 2018 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// request contains logic to make polling HTTP requests against an endpoint with optional host spoofing. - -package test - -import ( - "context" - "net/url" - "time" - - "k8s.io/client-go/kubernetes" - "knative.dev/pkg/test/logging" - "knative.dev/pkg/test/spoof" -) - -// RequestOption enables configuration of requests -// when polling for endpoint states. -type RequestOption = spoof.RequestOption - -// WithHeader will add the provided headers to the request. -// -// Deprecated: Use the spoof package version -var WithHeader = spoof.WithHeader - -// IsOneOfStatusCodes checks that the response code is equal to the given one. -// -// Deprecated: Use the spoof package version -var IsOneOfStatusCodes = spoof.IsOneOfStatusCodes - -// IsStatusOK checks that the response code is a 200. -// -// Deprecated: Use the spoof package version -var IsStatusOK = spoof.IsStatusOK - -// MatchesAllBodies checks that the *first* response body matches the "expected" body, otherwise failing. -// -// Deprecated: Use the spoof package version -var MatchesAllBodies = spoof.MatchesAllBodies - -// MatchesBody checks that the *first* response body matches the "expected" body, otherwise failing. -// -// Deprecated: Use the spoof package version -var MatchesBody = spoof.MatchesBody - -// MatchesAllOf combines multiple ResponseCheckers to one ResponseChecker with a logical AND. The -// checkers are executed in order. The first function to trigger an error or a retry will short-circuit -// the other functions (they will not be executed). -// -// This is useful for combining a body with a status check like: -// MatchesAllOf(IsStatusOK, MatchesBody("test")) -// -// The MatchesBody check will only be executed after the IsStatusOK has passed. -// -// Deprecated: Use the spoof package version -var MatchesAllOf = spoof.MatchesAllOf - -// WaitForEndpointState will poll an endpoint until inState indicates the state is achieved, -// or default timeout is reached. -// If resolvableDomain is false, it will use kubeClientset to look up the ingress and spoof -// the domain in the request headers, otherwise it will make the request directly to domain. -// desc will be used to name the metric that is emitted to track how long it took for the -// domain to get into the state checked by inState. Commas in `desc` must be escaped. -func WaitForEndpointState( - ctx context.Context, - kubeClient kubernetes.Interface, - logf logging.FormatLogger, - url *url.URL, - inState spoof.ResponseChecker, - desc string, - resolvable bool, - opts ...interface{}) (*spoof.Response, error) { - return WaitForEndpointStateWithTimeout(ctx, kubeClient, logf, url, inState, - desc, resolvable, Flags.SpoofRequestTimeout, opts...) -} - -// WaitForEndpointStateWithTimeout will poll an endpoint until inState indicates the state is achieved -// or the provided timeout is achieved. -// If resolvableDomain is false, it will use kubeClientset to look up the ingress and spoof -// the domain in the request headers, otherwise it will make the request directly to domain. -// desc will be used to name the metric that is emitted to track how long it took for the -// domain to get into the state checked by inState. Commas in `desc` must be escaped. -func WaitForEndpointStateWithTimeout( - ctx context.Context, - kubeClient kubernetes.Interface, - logf logging.FormatLogger, - url *url.URL, - inState spoof.ResponseChecker, - desc string, - resolvable bool, - timeout time.Duration, - opts ...interface{}) (*spoof.Response, error) { - - client, rOpts, err := makeSpoofClient(ctx, kubeClient, logf, url, resolvable, timeout, opts...) - if err != nil { - return nil, err - } - return client.WaitForEndpointState(ctx, url, inState, desc, rOpts...) -} - -func makeSpoofClient( - ctx context.Context, - kubeClient kubernetes.Interface, - logf logging.FormatLogger, - url *url.URL, - resolvable bool, - timeout time.Duration, - opts ...interface{}) (*spoof.SpoofingClient, []spoof.RequestOption, error) { - - var tOpts []spoof.TransportOption - var rOpts []spoof.RequestOption - - for _, opt := range opts { - switch o := opt.(type) { - case spoof.RequestOption: - rOpts = append(rOpts, o) - case spoof.TransportOption: - tOpts = append(tOpts, o) - } - } - - client, err := NewSpoofingClient(ctx, kubeClient, logf, url.Hostname(), resolvable, tOpts...) - if err != nil { - return nil, nil, err - } - client.RequestTimeout = timeout - - return client, rOpts, nil -} - -func CheckEndpointState( - ctx context.Context, - kubeClient kubernetes.Interface, - logf logging.FormatLogger, - url *url.URL, - inState spoof.ResponseChecker, - desc string, - resolvable bool, - opts ...interface{}, -) (*spoof.Response, error) { - client, rOpts, err := makeSpoofClient(ctx, kubeClient, logf, url, resolvable, Flags.SpoofRequestTimeout, opts...) - if err != nil { - return nil, err - } - return client.CheckEndpointState(ctx, url, inState, desc, rOpts...) -} diff --git a/vendor/knative.dev/pkg/test/spoof/error_checks.go b/vendor/knative.dev/pkg/test/spoof/error_checks.go deleted file mode 100644 index b0638ad34..000000000 --- a/vendor/knative.dev/pkg/test/spoof/error_checks.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// spoof contains logic to make polling HTTP requests against an endpoint with optional host spoofing. - -package spoof - -import ( - "errors" - "net" - "net/http" - "strings" -) - -func isTCPTimeout(err error) bool { - if err == nil { - return false - } - var errNet net.Error - if !errors.As(err, &errNet) { - return false - } - return errNet.Timeout() -} - -func isDNSError(err error) bool { - if err == nil { - return false - } - // Checking by casting to url.Error and casting the nested error - // seems to be not as robust as string check. - msg := strings.ToLower(err.Error()) - // Example error message: - // > Get http://this.url.does.not.exist: dial tcp: lookup this.url.does.not.exist on 127.0.0.1:53: no such host - return strings.Contains(msg, "no such host") || strings.Contains(msg, ":53") -} - -func isConnectionRefused(err error) bool { - // The alternative for the string check is: - // errNo := (((err.(*url.Error)).Err.(*net.OpError)).Err.(*os.SyscallError).Err).(syscall.Errno) - // if errNo == syscall.Errno(0x6f) {...} - // But with assertions, of course. - return err != nil && strings.Contains(err.Error(), "connect: connection refused") -} - -func isConnectionReset(err error) bool { - return err != nil && strings.Contains(err.Error(), "connection reset by peer") -} - -func isNoRouteToHostError(err error) bool { - return err != nil && strings.Contains(err.Error(), "connect: no route to host") -} - -func isResponseDNSError(resp *Response) bool { - // no such host with 502 is sent back from istio-ingressgateway when it fails to resolve domain. - return resp.StatusCode == http.StatusBadGateway && strings.Contains(string(resp.Body), "no such host") -} diff --git a/vendor/knative.dev/pkg/test/spoof/request.go b/vendor/knative.dev/pkg/test/spoof/request.go deleted file mode 100644 index df26e8fae..000000000 --- a/vendor/knative.dev/pkg/test/spoof/request.go +++ /dev/null @@ -1,38 +0,0 @@ -/* -Copyright 2020 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package spoof - -import "net/http" - -// RequestOption enables configuration of requests -// when polling for endpoint states. -type RequestOption func(*http.Request) - -// WithHeader will add the provided headers to the request. -func WithHeader(header http.Header) RequestOption { - return func(r *http.Request) { - if r.Header == nil { - r.Header = header - return - } - for key, values := range header { - for _, value := range values { - r.Header.Add(key, value) - } - } - } -} diff --git a/vendor/knative.dev/pkg/test/spoof/response_checks.go b/vendor/knative.dev/pkg/test/spoof/response_checks.go deleted file mode 100644 index c19d9dc8e..000000000 --- a/vendor/knative.dev/pkg/test/spoof/response_checks.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2020 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package spoof - -import ( - "fmt" - "net/http" - "strings" - "sync" - - "k8s.io/apimachinery/pkg/util/sets" -) - -// MatchesBody checks that the *first* response body matches the "expected" body, otherwise failing. -func MatchesBody(expected string) ResponseChecker { - return func(resp *Response) (bool, error) { - if !strings.Contains(string(resp.Body), expected) { - // Returning (true, err) causes SpoofingClient.Poll to fail. - return true, fmt.Errorf("body = %s, want: %s", string(resp.Body), expected) - } - - return true, nil - } -} - -// MatchesAllOf combines multiple ResponseCheckers to one ResponseChecker with a logical AND. The -// checkers are executed in order. The first function to trigger an error or a retry will short-circuit -// the other functions (they will not be executed). -// -// This is useful for combining a body with a status check like: -// MatchesAllOf(IsStatusOK, MatchesBody("test")) -// -// The MatchesBody check will only be executed after the IsStatusOK has passed. -func MatchesAllOf(checkers ...ResponseChecker) ResponseChecker { - return func(resp *Response) (bool, error) { - for _, checker := range checkers { - if done, err := checker(resp); err != nil || !done { - return done, err - } - } - return true, nil - } -} - -// MatchesAllBodies checks that the *first* response body matches the "expected" body, otherwise failing. -func MatchesAllBodies(all ...string) ResponseChecker { - var m sync.Mutex - // This helps with two things: - // 1. we can use Equal on sets - // 2. it will collapse the duplicates - want := sets.New[string](all...) - seen := make(sets.Set[string], len(all)) - - return func(resp *Response) (bool, error) { - bs := string(resp.Body) - for expected := range want { - if !strings.Contains(bs, expected) { - // See if the next one matches. - continue - } - - m.Lock() - defer m.Unlock() - seen.Insert(expected) - - // Stop once we've seen them all. - return want.Equal(seen), nil - } - - // Returning (true, err) causes SpoofingClient.Poll to fail. - return true, fmt.Errorf("body = %s, want one of: %s", bs, all) - } -} - -// IsStatusOK checks that the response code is a 200. -func IsStatusOK(resp *Response) (bool, error) { - return IsOneOfStatusCodes(http.StatusOK)(resp) -} - -// IsOneOfStatusCodes checks that the response code is equal to the given one. -func IsOneOfStatusCodes(codes ...int) ResponseChecker { - return func(resp *Response) (bool, error) { - for _, code := range codes { - if resp.StatusCode == code { - return true, nil - } - } - - return true, fmt.Errorf("status = %d %s, want one of: %v", resp.StatusCode, resp.Status, codes) - } -} diff --git a/vendor/knative.dev/pkg/test/spoof/spoof.go b/vendor/knative.dev/pkg/test/spoof/spoof.go deleted file mode 100644 index 319e2ead8..000000000 --- a/vendor/knative.dev/pkg/test/spoof/spoof.go +++ /dev/null @@ -1,360 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// spoof contains logic to make polling HTTP requests against an endpoint with optional host spoofing. - -package spoof - -import ( - "context" - "errors" - "fmt" - "io" - "net" - "net/http" - "net/url" - "time" - - "k8s.io/apimachinery/pkg/util/wait" - "k8s.io/client-go/kubernetes" - "knative.dev/pkg/test/ingress" - "knative.dev/pkg/test/logging" - "knative.dev/pkg/test/zipkin" - "knative.dev/pkg/tracing/propagation/tracecontextb3" - - "go.opencensus.io/plugin/ochttp" - "go.opencensus.io/trace" -) - -// Response is a stripped down subset of http.Response. The is primarily useful -// for ResponseCheckers to inspect the response body without consuming it. -// Notably, Body is a byte slice instead of an io.ReadCloser. -type Response struct { - Status string - StatusCode int - Header http.Header - Body []byte -} - -func (r *Response) String() string { - return fmt.Sprintf("status: %d, body: %s, headers: %v", r.StatusCode, string(r.Body), r.Header) -} - -// https://medium.com/stupid-gopher-tricks/ensuring-go-interface-satisfaction-at-compile-time-1ed158e8fa17 -var dialContext = (&net.Dialer{}).DialContext - -// ResponseChecker is used to determine when SpoofingClient.Poll is done polling. -// This allows you to predicate wait.PollImmediate on the request's http.Response. -// -// See the apimachinery wait package: -// https://github.com/kubernetes/apimachinery/blob/cf7ae2f57dabc02a3d215f15ca61ae1446f3be8f/pkg/util/wait/wait.go#L172 -type ResponseChecker func(resp *Response) (done bool, err error) - -// ErrorRetryChecker is used to determine if an error should be retried or not. -// If an error should be retried, it should return true and the wrapped error to explain why to retry. -type ErrorRetryChecker func(e error) (retry bool, err error) - -// ResponseRetryChecker is used to determine if a response should be retried or not. -// If a response should be retried, it should return true and an error to explain why to retry. -// -// This is distinct from ResponseChecker in that it shall be used to retry responses, -// where the HTTP request was technically successful (it returned something) but indicates -// an error (e.g. the overload page of a loadbalancer). -type ResponseRetryChecker func(resp *Response) (retry bool, err error) - -// SpoofingClient is a minimal HTTP client wrapper that spoofs the domain of requests -// for non-resolvable domains. -type SpoofingClient struct { - Client *http.Client - RequestInterval time.Duration - RequestTimeout time.Duration - Logf logging.FormatLogger -} - -// TransportOption allows callers to customize the http.Transport used by a SpoofingClient -type TransportOption func(transport *http.Transport) *http.Transport - -// New returns a SpoofingClient that rewrites requests if the target domain is not `resolvable`. -// It does this by looking up the ingress at construction time, so reusing a client will not -// follow the ingress if it moves (or if there are multiple ingresses). -// -// If that's a problem, see test/request.go#WaitForEndpointState for oneshot spoofing. -func New( - ctx context.Context, - kubeClientset kubernetes.Interface, - logf logging.FormatLogger, - domain string, - resolvable bool, - endpointOverride string, - requestInterval, requestTimeout time.Duration, - opts ...TransportOption) (*SpoofingClient, error) { - endpoint, mapper, err := ResolveEndpoint(ctx, kubeClientset, domain, resolvable, endpointOverride) - if err != nil { - return nil, fmt.Errorf("failed to get the cluster endpoint: %w", err) - } - - // Spoof the hostname at the resolver level - logf("Spoofing %s -> %s", domain, endpoint) - transport := &http.Transport{ - DialContext: func(ctx context.Context, network, addr string) (conn net.Conn, e error) { - _, port, err := net.SplitHostPort(addr) - if err != nil { - return nil, err - } - // The original hostname:port is spoofed by replacing the hostname by the value - // returned by ResolveEndpoint. - return dialContext(ctx, network, net.JoinHostPort(endpoint, mapper(port))) - }, - } - - for _, opt := range opts { - transport = opt(transport) - } - - // Enable Zipkin tracing - roundTripper := &ochttp.Transport{ - Base: transport, - Propagation: tracecontextb3.TraceContextB3Egress, - } - - sc := &SpoofingClient{ - Client: &http.Client{Transport: roundTripper}, - RequestInterval: requestInterval, - RequestTimeout: requestTimeout, - Logf: logf, - } - return sc, nil -} - -// ResolveEndpoint resolves the endpoint address considering whether the domain is resolvable and taking into -// account whether the user overrode the endpoint address externally -func ResolveEndpoint(ctx context.Context, kubeClientset kubernetes.Interface, domain string, resolvable bool, endpointOverride string) (string, func(string) string, error) { - id := func(in string) string { return in } - // If the domain is resolvable, it can be used directly - if resolvable { - return domain, id, nil - } - // Otherwise, use the actual cluster endpoint - return ingress.GetIngressEndpoint(ctx, kubeClientset, endpointOverride) -} - -// Do dispatches to the underlying http.Client.Do, spoofing domains as needed -// and transforming the http.Response into a spoof.Response. -// Each response is augmented with "ZipkinTraceID" header that identifies the zipkin trace corresponding to the request. -func (sc *SpoofingClient) Do(req *http.Request, errorRetryCheckers ...interface{}) (*Response, error) { - return sc.Poll(req, func(*Response) (bool, error) { return true, nil }, errorRetryCheckers...) -} - -// Poll executes an http request until it satisfies the inState condition or, if there's an error, -// none of the error retry checkers permit a retry. -// If no retry checkers are specified `DefaultErrorRetryChecker` will be used. -func (sc *SpoofingClient) Poll(req *http.Request, inState ResponseChecker, checkers ...interface{}) (*Response, error) { - if len(checkers) == 0 { - checkers = []interface{}{ErrorRetryChecker(DefaultErrorRetryChecker), ResponseRetryChecker(DefaultResponseRetryChecker)} - } - - var resp *Response - err := wait.PollImmediate(sc.RequestInterval, sc.RequestTimeout, func() (bool, error) { - // Starting span to capture zipkin trace. - traceContext, span := trace.StartSpan(req.Context(), "SpoofingClient-Trace") - defer span.End() - rawResp, err := sc.Client.Do(req.WithContext(traceContext)) - if err != nil { - for _, checker := range checkers { - if ec, ok := checker.(ErrorRetryChecker); ok { - retry, newErr := ec(err) - if retry { - sc.Logf("Retrying %s: %v", req.URL.String(), newErr) - return false, nil - } - } - } - sc.Logf("NOT Retrying %s: %v", req.URL.String(), err) - return true, err - } - defer rawResp.Body.Close() - - body, err := io.ReadAll(rawResp.Body) - if err != nil { - return true, err - } - rawResp.Header.Add(zipkin.ZipkinTraceIDHeader, span.SpanContext().TraceID.String()) - - resp = &Response{ - Status: rawResp.Status, - StatusCode: rawResp.StatusCode, - Header: rawResp.Header, - Body: body, - } - - // This is distinct from inState in that it allows us to uniformly check for - // error responses to retry HTTP requests that have technically been successful, - // but haven't reached their destination (e.g. got a loadbalancer overload page). - for _, checker := range checkers { - if rc, ok := checker.(ResponseRetryChecker); ok { - retry, newErr := rc(resp) - if retry { - sc.Logf("Retrying %s: %v", req.URL.String(), newErr) - return false, nil - } - } - } - - return inState(resp) - }) - - if resp != nil { - sc.logZipkinTrace(resp) - } - - if err != nil { - return resp, fmt.Errorf("response: %s did not pass checks: %w", resp, err) - } - return resp, nil -} - -// DefaultErrorRetryChecker implements the defaults for retrying on error. -func DefaultErrorRetryChecker(err error) (bool, error) { - if isTCPTimeout(err) { - return true, fmt.Errorf("retrying for TCP timeout: %w", err) - } - // Retrying on DNS error, since we may be using sslip.io or nip.io in tests. - if isDNSError(err) { - return true, fmt.Errorf("retrying for DNS error: %w", err) - } - // Repeat the poll on `connection refused` errors, which are usually transient Istio errors. - if isConnectionRefused(err) { - return true, fmt.Errorf("retrying for connection refused: %w", err) - } - if isConnectionReset(err) { - return true, fmt.Errorf("retrying for connection reset: %w", err) - } - // Retry on connection/network errors. - if errors.Is(err, io.EOF) { - return true, fmt.Errorf("retrying for: %w", err) - } - // No route to host errors are in the same category as connection refused errors and - // are usually transient. - if isNoRouteToHostError(err) { - return true, fmt.Errorf("retrying for 'no route to host' error: %w", err) - } - return false, err -} - -// DefaultResponseRetryChecker implements the defaults for retrying on response. -func DefaultResponseRetryChecker(resp *Response) (bool, error) { - if isResponseDNSError(resp) { - return true, fmt.Errorf("retrying for DNS related failure response: %v", resp) - } - return false, nil -} - -// logZipkinTrace provides support to log Zipkin Trace for param: spoofResponse -// We only log Zipkin trace for HTTP server errors i.e for HTTP status codes between 500 to 600 -func (sc *SpoofingClient) logZipkinTrace(spoofResp *Response) { - if !zipkin.IsTracingEnabled() || spoofResp.StatusCode < http.StatusInternalServerError || spoofResp.StatusCode >= 600 { - return - } - - traceID := spoofResp.Header.Get(zipkin.ZipkinTraceIDHeader) - sc.Logf("Logging Zipkin Trace for: %s", traceID) - - json, err := zipkin.JSONTrace(traceID /* We don't know the expected number of spans */, -1, 5*time.Second) - if err != nil { - var errTimeout *zipkin.TimeoutError - if !errors.As(err, &errTimeout) { - sc.Logf("Error getting zipkin trace: %v", err) - } - } - - sc.Logf("%s", json) -} - -func (sc *SpoofingClient) WaitForEndpointState( - ctx context.Context, - url *url.URL, - inState ResponseChecker, - desc string, - opts ...RequestOption) (*Response, error) { - - return sc.endpointState( - ctx, - url, - inState, - desc, - func(req *http.Request, check ResponseChecker) (*Response, error) { return sc.Poll(req, check) }, - "WaitForEndpointState", - opts...) -} - -func (sc *SpoofingClient) endpointState( - ctx context.Context, - url *url.URL, - inState ResponseChecker, - desc string, - f func(*http.Request, ResponseChecker) (*Response, error), - logName string, - opts ...RequestOption) (*Response, error) { - defer logging.GetEmitableSpan(ctx, logName+"/"+desc).End() - - if url.Scheme == "" || url.Host == "" { - return nil, fmt.Errorf("invalid URL: %q", url.String()) - } - - req, err := http.NewRequest(http.MethodGet, url.String(), nil) - if err != nil { - return nil, err - } - - for _, opt := range opts { - opt(req) - } - - return f(req, inState) -} - -func (sc *SpoofingClient) Check(req *http.Request, inState ResponseChecker, checkers ...interface{}) (*Response, error) { - resp, err := sc.Do(req, checkers...) - if err != nil { - return nil, err - } - - ok, err := inState(resp) - if err != nil { - return resp, fmt.Errorf("response: %s did not pass checks: %w", resp, err) - } - if ok { - return resp, nil - } - - return nil, err -} - -func (sc *SpoofingClient) CheckEndpointState( - ctx context.Context, - url *url.URL, - inState ResponseChecker, - desc string, - opts ...RequestOption) (*Response, error) { - return sc.endpointState( - ctx, - url, - inState, - desc, - func(req *http.Request, check ResponseChecker) (*Response, error) { return sc.Check(req, check) }, - "CheckEndpointState", - opts...) -} diff --git a/vendor/knative.dev/pkg/test/test-reconciler-codegen.sh b/vendor/knative.dev/pkg/test/test-reconciler-codegen.sh deleted file mode 100644 index c6bb3e20c..000000000 --- a/vendor/knative.dev/pkg/test/test-reconciler-codegen.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2020 The Knative Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -o errexit -set -o nounset -set -o pipefail - -source $(dirname $0)/../vendor/knative.dev/hack/library.sh - -CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)} -KNATIVE_CODEGEN_PKG=${KNATIVE_CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/knative.dev/pkg 2>/dev/null || echo ../pkg)} - -GENCLIENT_PKG=knative.dev/pkg/test/genclient - -echo "Pre-deleting $(dirname $0)/genclient" -rm -rf $(dirname $0)/genclient - -header "Test Generated Reconciler Builds." - -chmod +x ${CODEGEN_PKG}/generate-groups.sh - -${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \ - ${GENCLIENT_PKG} knative.dev/pkg/apis/test \ - "example:v1alpha1" \ - --go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt - -# Knative Injection -${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \ - ${GENCLIENT_PKG} knative.dev/pkg/apis/test \ - "example:v1alpha1" \ - --go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt \ - --force-genreconciler-kinds "Foo" - -${CODEGEN_PKG}/generate-groups.sh "deepcopy,client,informer,lister" \ - ${GENCLIENT_PKG}/pub knative.dev/pkg/apis/test \ - "pub:v1alpha1" \ - --go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt - -# Knative Injection -${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \ - ${GENCLIENT_PKG}/pub knative.dev/pkg/apis/test \ - "pub:v1alpha1" \ - --go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt - -if ! go build -v $(dirname $0)/genclient/... ; then - exit 1 -fi - -echo "Finished, deleting $(dirname $0)/genclient" -rm -rf $(dirname $0)/genclient diff --git a/vendor/knative.dev/pkg/test/tinterface.go b/vendor/knative.dev/pkg/test/tinterface.go deleted file mode 100644 index 530ff0a2e..000000000 --- a/vendor/knative.dev/pkg/test/tinterface.go +++ /dev/null @@ -1,40 +0,0 @@ -/* -Copyright 2019 The Knative Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Defines an interface of commonality between testing.T and logging.TLogger -// Allows most library functions to be shared -// Simplifies coexistence with TLogger - -package test - -// T is an interface mimicking *testing.T. -// Deprecated: Do not use this. Define your own interface. -type T interface { - Name() string - Helper() - SkipNow() - Cleanup(func()) - Log(args ...interface{}) - Error(args ...interface{}) -} - -// TLegacy is an interface mimicking *testing.T. -// Deprecated: Do not use this. Define your own interface. -type TLegacy interface { - T - Logf(fmt string, args ...interface{}) // It gets passed to things in logstream - Fatal(args ...interface{}) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 003015645..bab0a19d1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -883,16 +883,11 @@ knative.dev/pkg/reconciler knative.dev/pkg/signals knative.dev/pkg/system knative.dev/pkg/system/testing -knative.dev/pkg/test -knative.dev/pkg/test/environment knative.dev/pkg/test/helpers -knative.dev/pkg/test/ingress knative.dev/pkg/test/logging -knative.dev/pkg/test/logstream knative.dev/pkg/test/logstream/v2 knative.dev/pkg/test/monitoring knative.dev/pkg/test/security -knative.dev/pkg/test/spoof knative.dev/pkg/test/zipkin knative.dev/pkg/tracing knative.dev/pkg/tracing/config