mirror of
https://github.com/kubernetes/client-go.git
synced 2026-06-27 12:15:25 +00:00
Compare commits
59 Commits
kubernetes
...
kubernetes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
80a1a93c2f | ||
|
|
637fc595d1 | ||
|
|
069aa55f4a | ||
|
|
44c2c549a5 | ||
|
|
96d4b4ca2c | ||
|
|
5abdc64bf8 | ||
|
|
e4cdb82809 | ||
|
|
3c67f637e2 | ||
|
|
935aad3790 | ||
|
|
f0e0a63eea | ||
|
|
3e37d3cec6 | ||
|
|
e85d69084a | ||
|
|
e4ab670a95 | ||
|
|
f6af94938b | ||
|
|
b34ddfd55a | ||
|
|
46aef4b64f | ||
|
|
0f8ad595c9 | ||
|
|
ea09349e3b | ||
|
|
f78d31a2bc | ||
|
|
1d2c64df00 | ||
|
|
0810080103 | ||
|
|
0976f4afe2 | ||
|
|
0673906c42 | ||
|
|
a2e13ccd49 | ||
|
|
127c8ce629 | ||
|
|
26011c05ab | ||
|
|
9bcc910985 | ||
|
|
3ed0010e30 | ||
|
|
c0015c0cc1 | ||
|
|
22ef81a898 | ||
|
|
7d76947ccd | ||
|
|
7615511cc0 | ||
|
|
a99ac36e1a | ||
|
|
424bde0e01 | ||
|
|
958c03a8dd | ||
|
|
9a62005bf9 | ||
|
|
0f3c6ef2dc | ||
|
|
4deb1a7db2 | ||
|
|
d64f019211 | ||
|
|
73e7057101 | ||
|
|
2c91b666c2 | ||
|
|
94836903b2 | ||
|
|
4ea001dc73 | ||
|
|
f7ff47eb37 | ||
|
|
45ef4fc0dc | ||
|
|
c428844852 | ||
|
|
a0a9a3744f | ||
|
|
fa64ba9235 | ||
|
|
ed62839de3 | ||
|
|
85e546b378 | ||
|
|
465fab1523 | ||
|
|
c076c6e063 | ||
|
|
171f146b90 | ||
|
|
98cbc2c6ac | ||
|
|
5551f5649d | ||
|
|
501db86fbe | ||
|
|
ce329ac04e | ||
|
|
dd7f3ad83f | ||
|
|
ba984c792f |
114
Godeps/Godeps.json
generated
114
Godeps/Godeps.json
generated
@@ -14,18 +14,6 @@
|
||||
"ImportPath": "github.com/Azure/go-autorest",
|
||||
"Rev": "v11.1.2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/NYTimes/gziphandler",
|
||||
"Rev": "56545f4a5d46"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/PuerkitoBio/purell",
|
||||
"Rev": "v1.0.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/PuerkitoBio/urlesc",
|
||||
"Rev": "5bd2802263f2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew",
|
||||
"Rev": "v1.1.1"
|
||||
@@ -42,41 +30,17 @@
|
||||
"ImportPath": "github.com/elazarl/goproxy",
|
||||
"Rev": "c4fc26588b6e"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/emicklei/go-restful",
|
||||
"Rev": "ff4f55a20633"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/evanphx/json-patch",
|
||||
"Rev": "v4.2.0"
|
||||
"Rev": "5858425f7550"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/fsnotify/fsnotify",
|
||||
"Rev": "v1.4.7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/ghodss/yaml",
|
||||
"Rev": "73d445a93680"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-openapi/jsonpointer",
|
||||
"Rev": "46af16f9f7b1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-openapi/jsonreference",
|
||||
"Rev": "13c6e3589ad9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-openapi/spec",
|
||||
"Rev": "6aced65f8501"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-openapi/swag",
|
||||
"Rev": "1d0bd113de87"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gogo/protobuf",
|
||||
"Rev": "v0.0.0-20190410021324-65acae22fc9"
|
||||
"Rev": "342cbe0a0415"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/golang/groupcache",
|
||||
@@ -96,11 +60,11 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/gofuzz",
|
||||
"Rev": "v1.0.0"
|
||||
"Rev": "24818f796faf"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/google/uuid",
|
||||
"Rev": "v1.1.1"
|
||||
"Rev": "v1.0.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/googleapis/gnostic",
|
||||
@@ -108,7 +72,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gophercloud/gophercloud",
|
||||
"Rev": "v0.1.0"
|
||||
"Rev": "c818fa66e4c8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gregjones/httpcache",
|
||||
@@ -128,31 +92,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/json-iterator/go",
|
||||
"Rev": "v1.1.6"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kisielk/errcheck",
|
||||
"Rev": "v1.2.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kisielk/gotool",
|
||||
"Rev": "v1.0.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/pretty",
|
||||
"Rev": "v0.1.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/pty",
|
||||
"Rev": "v1.1.1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/text",
|
||||
"Rev": "v0.1.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mailru/easyjson",
|
||||
"Rev": "d5b7844b561a"
|
||||
"Rev": "ab8a2e0c74be"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/modern-go/concurrent",
|
||||
@@ -162,21 +102,17 @@
|
||||
"ImportPath": "github.com/modern-go/reflect2",
|
||||
"Rev": "v1.0.1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/munnerz/goautoneg",
|
||||
"Rev": "a547fc61f48d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mxk/go-flowrate",
|
||||
"Rev": "cca7078d478f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/onsi/ginkgo",
|
||||
"Rev": "v1.8.0"
|
||||
"Rev": "v1.6.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/onsi/gomega",
|
||||
"Rev": "v1.5.0"
|
||||
"Rev": "5533ce8a0da3"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/peterbourgon/diskv",
|
||||
@@ -186,21 +122,13 @@
|
||||
"ImportPath": "github.com/pmezard/go-difflib",
|
||||
"Rev": "v1.0.0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/afero",
|
||||
"Rev": "v1.2.2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/spf13/pflag",
|
||||
"Rev": "v1.0.3"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/objx",
|
||||
"Rev": "v0.1.0"
|
||||
"Rev": "v1.0.1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify",
|
||||
"Rev": "v1.3.0"
|
||||
"Rev": "v1.2.2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/crypto",
|
||||
@@ -208,7 +136,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net",
|
||||
"Rev": "65e2d4e15006"
|
||||
"Rev": "cdfb69ac37fc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2",
|
||||
@@ -240,7 +168,7 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/check.v1",
|
||||
"Rev": "788fd7840127"
|
||||
"Rev": "20d25e280405"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/fsnotify.v1",
|
||||
@@ -256,19 +184,15 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/yaml.v2",
|
||||
"Rev": "v2.2.2"
|
||||
"Rev": "v2.2.1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/api",
|
||||
"Rev": "42d28c278e58"
|
||||
"Rev": "463df2a5c347"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/apimachinery",
|
||||
"Rev": "f97a4e5b4abc"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/gengo",
|
||||
"Rev": "0689ccc1d7d6"
|
||||
"Rev": "f2f3a405f61d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/klog",
|
||||
@@ -276,15 +200,11 @@
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/kube-openapi",
|
||||
"Rev": "33be087ad058"
|
||||
"Rev": "b3a7cee44a30"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/utils",
|
||||
"Rev": "c55fbcfc754a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "sigs.k8s.io/structured-merge-diff",
|
||||
"Rev": "15d366b2352e"
|
||||
"Rev": "c2654d5206da"
|
||||
},
|
||||
{
|
||||
"ImportPath": "sigs.k8s.io/yaml",
|
||||
|
||||
10
INSTALL.md
10
INSTALL.md
@@ -65,7 +65,7 @@ for each follows.
|
||||
### Go modules
|
||||
|
||||
Dependency management tools are built into go 1.11+ in the form of [go modules](https://github.com/golang/go/wiki/Modules).
|
||||
These are used by the main Kubernetes repo (>= 1.15) and `client-go` (on master, and v12.0.0+) to manage dependencies.
|
||||
These are used by the main Kubernetes repo (>= 1.15) and `client-go` (on master, and v12.0.0+ once released) to manage dependencies.
|
||||
When using `client-go` v12.0.0+ and go 1.11.4+, go modules are the recommended dependency management tool.
|
||||
|
||||
If you are using go 1.11 or 1.12 and are working with a project located within `$GOPATH`,
|
||||
@@ -83,10 +83,10 @@ go mod init
|
||||
```
|
||||
|
||||
Indicate which version of `client-go` your project requires.
|
||||
For `client-go` on v12.0.0 (and later), this is a single step:
|
||||
For `client-go` on master (and once version v12.0.0 is released), this is a single step:
|
||||
|
||||
```sh
|
||||
go get k8s.io/client-go@v12.0.0
|
||||
go get k8s.io/client-go@master # or v12.0.0+ once released
|
||||
```
|
||||
|
||||
For `client-go` prior to v12.0.0, you also need to indicate the required versions of `k8s.io/api` and `k8s.io/apimachinery`:
|
||||
@@ -119,7 +119,7 @@ your project:
|
||||
package: ( your project's import path ) # e.g. github.com/foo/bar
|
||||
import:
|
||||
- package: k8s.io/client-go
|
||||
version: v12.0.0 # replace v12.0.0 with the required version
|
||||
version: v11.0.0 # replace v11.0.0 with the required version
|
||||
```
|
||||
|
||||
Second, add a Go file that imports `client-go` somewhere in your project,
|
||||
@@ -152,7 +152,7 @@ requests can override the version manually in `glide.yaml`. For example:
|
||||
package: ( your project's import path ) # e.g. github.com/foo/bar
|
||||
import:
|
||||
- package: k8s.io/client-go
|
||||
version: v12.0.0 # replace v12.0.0 with the required version
|
||||
version: v11.0.0 # replace v11.0.0 with the required version
|
||||
# Use a newer version of go-spew even though client-go wants an old one.
|
||||
- package: github.com/davecgh/go-spew
|
||||
version: v1.1.0
|
||||
|
||||
25
README.md
25
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
Go clients for talking to a [kubernetes](http://kubernetes.io/) cluster.
|
||||
|
||||
We currently recommend using the v12.0.0 tag. See [INSTALL.md](/INSTALL.md) for
|
||||
We currently recommend using the v11.0.0 tag. See [INSTALL.md](/INSTALL.md) for
|
||||
detailed installation instructions. `go get k8s.io/client-go/...` works, but
|
||||
will build `master`, which doesn't handle the dependencies well.
|
||||
|
||||
@@ -92,16 +92,16 @@ We will backport bugfixes--but not new features--into older versions of
|
||||
|
||||
#### Compatibility matrix
|
||||
|
||||
| | Kubernetes 1.9 | Kubernetes 1.10 | Kubernetes 1.11 | Kubernetes 1.12 | Kubernetes 1.13 | Kubernetes 1.14 | Kubernetes 1.15 |
|
||||
|---------------------|----------------|-----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
|
||||
| client-go 6.0 | ✓ | +- | +- | +- | +- | +- | +- |
|
||||
| client-go 7.0 | +- | ✓ | +- | +- | +- | +- | +- |
|
||||
| client-go 8.0 | +- | +- | ✓ | +- | +- | +- | +- |
|
||||
| client-go 9.0 | +- | +- | +- | ✓ | +- | +- | +- |
|
||||
| client-go 10.0 | +- | +- | +- | +- | ✓ | +- | +- |
|
||||
| client-go 11.0 | +- | +- | +- | +- | +- | ✓ | +- |
|
||||
| client-go 12.0 | +- | +- | +- | +- | +- | +- | ✓ |
|
||||
| client-go HEAD | +- | +- | +- | +- | +- | +- | +- |
|
||||
| | Kubernetes 1.8 | Kubernetes 1.9 | Kubernetes 1.10 | Kubernetes 1.11 | Kubernetes 1.12 | Kubernetes 1.13 | Kubernetes 1.14 |
|
||||
|---------------------|----------------|----------------|-----------------|-----------------|-----------------|-----------------|-----------------|
|
||||
| client-go 5.0 | ✓ | +- | +- | +- | +- | +- | +- |
|
||||
| client-go 6.0 | +- | ✓ | +- | +- | +- | +- | +- |
|
||||
| client-go 7.0 | +- | +- | ✓ | +- | +- | +- | +- |
|
||||
| client-go 8.0 | +- | +- | +- | ✓ | +- | +- | +- |
|
||||
| client-go 9.0 | +- | +- | +- | +- | ✓ | +- | +- |
|
||||
| client-go 10.0 | +- | +- | +- | +- | +- | ✓ | +- |
|
||||
| client-go 11.0 | +- | +- | +- | +- | +- | +- | ✓ |
|
||||
| client-go HEAD | +- | +- | +- | +- | +- | +- | +- |
|
||||
|
||||
Key:
|
||||
|
||||
@@ -131,10 +131,9 @@ between client-go versions.
|
||||
| client-go 6.0 | Kubernetes main repo, 1.9 branch | = - |
|
||||
| client-go 7.0 | Kubernetes main repo, 1.10 branch | = - |
|
||||
| client-go 8.0 | Kubernetes main repo, 1.11 branch | =- |
|
||||
| client-go 9.0 | Kubernetes main repo, 1.12 branch | =- |
|
||||
| client-go 9.0 | Kubernetes main repo, 1.12 branch | ✓ |
|
||||
| client-go 10.0 | Kubernetes main repo, 1.13 branch | ✓ |
|
||||
| client-go 11.0 | Kubernetes main repo, 1.14 branch | ✓ |
|
||||
| client-go 12.0 | Kubernetes main repo, 1.15 branch | ✓ |
|
||||
| client-go HEAD | Kubernetes main repo, master branch | ✓ |
|
||||
|
||||
Key:
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# INSTRUCTIONS AT https://kubernetes.io/security/
|
||||
|
||||
cjcullen
|
||||
joelsmith
|
||||
jessfraz
|
||||
liggitt
|
||||
philips
|
||||
tallclair
|
||||
|
||||
@@ -16,4 +16,4 @@ limitations under the License.
|
||||
|
||||
// Package discovery provides ways to discover server-supported
|
||||
// API groups, versions and resources.
|
||||
package discovery // import "k8s.io/client-go/discovery"
|
||||
package discovery
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
# Create, Update & Delete Deployment with the Dynamic Package
|
||||
|
||||
This example program demonstrates the fundamental operations for managing on
|
||||
[Deployment][1] resources, such as `Create`, `List`, `Update` and `Delete` using client-go's `dynamic` package.
|
||||
|
||||
## Typed Vs. Dynamic
|
||||
The code in this directory is based on a similar [example that uses Kubernetes typed client sets][2]. The typed client sets make it simple to communicate with the API server using pre-generated local API objects to achieve an RPC-like programming experience. Typed clients uses program compilations to enforce data safety and some validation. However, when using typed clients, programs are forced to be tightly coupled with the version and the types used.
|
||||
|
||||
|
||||
The `dynamic` package on the other hand, uses a simple type, `unstructured.Unstructured`, to represent all object values from the API server. Type `Unstructured` uses a collection of nested `map[string]interface{}` values to create an internal structure that closely resemble the REST payload from the server.
|
||||
|
||||
The dynamic package defers all data bindings until runtime. This means programs that use the dynamic client will not get any of the benefits of type validation until the program is running. This may be a problem for certain types of applications that require strong data type check and validation.
|
||||
|
||||
Being loosely coupled, however, means that programs that uses the `dynamic` package do not require recompilation when the client API changes. The client program has more flexibility in handling updates to the API surface without knowing ahead of time what those changes are.
|
||||
|
||||
|
||||
## Running this example
|
||||
|
||||
Make sure you have a Kubernetes cluster and `kubectl` is configured:
|
||||
```
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
Compile this example on your workstation:
|
||||
|
||||
```
|
||||
cd dynamic-create-update-delete-deployment
|
||||
go build -o ./app
|
||||
```
|
||||
|
||||
Now, run this application on your workstation with your local kubeconfig file:
|
||||
|
||||
```
|
||||
./app
|
||||
# or specify a kubeconfig file with flag
|
||||
./app -kubeconfig=$HOME/.kube/config
|
||||
```
|
||||
|
||||
Running this command will execute the following operations on your cluster:
|
||||
|
||||
1. **Create Deployment:** This will create a 2 replica Deployment. Verify with
|
||||
`kubectl get pods`.
|
||||
2. **Update Deployment:** This will update the Deployment resource created in
|
||||
previous step by setting the replica count to 1 and changing the container
|
||||
image to `nginx:1.13`. You are encouraged to inspect the retry loop that
|
||||
handles conflicts. Verify the new replica count and container image with
|
||||
`kubectl describe deployment demo`.
|
||||
3. **List Deployments:** This will retrieve Deployments in the `default`
|
||||
namespace and print their names and replica counts.
|
||||
4. **Delete Deployment:** This will delete the Deployment object and its
|
||||
dependent ReplicaSet resource. Verify with `kubectl get deployments`.
|
||||
|
||||
Each step is separated by an interactive prompt. You must hit the
|
||||
<kbd>Return</kbd> key to proceed to the next step. You can use these prompts as
|
||||
a break to take time to run `kubectl` and inspect the result of the operations
|
||||
executed.
|
||||
|
||||
You should see an output like the following:
|
||||
|
||||
```
|
||||
Creating deployment...
|
||||
Created deployment "demo-deployment".
|
||||
-> Press Return key to continue.
|
||||
|
||||
Updating deployment...
|
||||
Updated deployment...
|
||||
-> Press Return key to continue.
|
||||
|
||||
Listing deployments in namespace "default":
|
||||
* demo-deployment (1 replicas)
|
||||
-> Press Return key to continue.
|
||||
|
||||
Deleting deployment...
|
||||
Deleted deployment.
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
|
||||
Successfully running this program will clean the created artifacts. If you
|
||||
terminate the program without completing, you can clean up the created
|
||||
deployment with:
|
||||
|
||||
kubectl delete deploy demo-deployment
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If you are getting the following error, make sure Kubernetes version of your
|
||||
cluster is v1.13 or higher in `kubectl version`:
|
||||
|
||||
panic: the server could not find the requested resource
|
||||
|
||||
[1]: https://kubernetes.io/docs/user-guide/deployments/
|
||||
[2]: ../create-update-delete-deployment
|
||||
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Note: the example only works with the code within the same release/branch.
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/util/homedir"
|
||||
"k8s.io/client-go/util/retry"
|
||||
//
|
||||
// Uncomment to load all auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth
|
||||
//
|
||||
// Or uncomment to load specific auth plugins
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/azure"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
|
||||
// _ "k8s.io/client-go/plugin/pkg/client/auth/openstack"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var kubeconfig *string
|
||||
if home := homedir.HomeDir(); home != "" {
|
||||
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
|
||||
} else {
|
||||
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
|
||||
}
|
||||
flag.Parse()
|
||||
|
||||
namespace := "default"
|
||||
|
||||
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
client, err := dynamic.NewForConfig(config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
|
||||
|
||||
deployment := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "Deployment",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "demo-deployment",
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"replicas": 2,
|
||||
"selector": map[string]interface{}{
|
||||
"matchLabels": map[string]interface{}{
|
||||
"app": "demo",
|
||||
},
|
||||
},
|
||||
"template": map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"labels": map[string]interface{}{
|
||||
"app": "demo",
|
||||
},
|
||||
},
|
||||
|
||||
"spec": map[string]interface{}{
|
||||
"containers": []map[string]interface{}{
|
||||
{
|
||||
"name": "web",
|
||||
"image": "nginx:1.12",
|
||||
"ports": []map[string]interface{}{
|
||||
{
|
||||
"name": "http",
|
||||
"protocol": "TCP",
|
||||
"containerPort": 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Create Deployment
|
||||
fmt.Println("Creating deployment...")
|
||||
result, err := client.Resource(deploymentRes).Namespace(namespace).Create(deployment, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf("Created deployment %q.\n", result.GetName())
|
||||
|
||||
// Update Deployment
|
||||
prompt()
|
||||
fmt.Println("Updating deployment...")
|
||||
// You have two options to Update() this Deployment:
|
||||
//
|
||||
// 1. Modify the "deployment" variable and call: Update(deployment).
|
||||
// This works like the "kubectl replace" command and it overwrites/loses changes
|
||||
// made by other clients between you Create() and Update() the object.
|
||||
// 2. Modify the "result" returned by Get() and retry Update(result) until
|
||||
// you no longer get a conflict error. This way, you can preserve changes made
|
||||
// by other clients between Create() and Update(). This is implemented below
|
||||
// using the retry utility package included with client-go. (RECOMMENDED)
|
||||
//
|
||||
// More Info:
|
||||
// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
|
||||
|
||||
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
// Retrieve the latest version of Deployment before attempting update
|
||||
// RetryOnConflict uses exponential backoff to avoid exhausting the apiserver
|
||||
result, getErr := client.Resource(deploymentRes).Namespace(namespace).Get("demo-deployment", metav1.GetOptions{})
|
||||
if getErr != nil {
|
||||
panic(fmt.Errorf("failed to get latest version of Deployment: %v", getErr))
|
||||
}
|
||||
|
||||
// update replicas to 1
|
||||
if err := unstructured.SetNestedField(result.Object, int64(1), "spec", "replicas"); err != nil {
|
||||
panic(fmt.Errorf("failed to set replica value: %v", err))
|
||||
}
|
||||
|
||||
// extract spec containers
|
||||
containers, found, err := unstructured.NestedSlice(result.Object, "spec", "template", "spec", "containers")
|
||||
if err != nil || !found || containers == nil {
|
||||
panic(fmt.Errorf("deployment containers not found or error in spec: %v", err))
|
||||
}
|
||||
|
||||
// update container[0] image
|
||||
if err := unstructured.SetNestedField(containers[0].(map[string]interface{}), "nginx:1.13", "image"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := unstructured.SetNestedField(result.Object, containers, "spec", "template", "spec", "containers"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, updateErr := client.Resource(deploymentRes).Namespace(namespace).Update(result, metav1.UpdateOptions{})
|
||||
return updateErr
|
||||
})
|
||||
if retryErr != nil {
|
||||
panic(fmt.Errorf("update failed: %v", retryErr))
|
||||
}
|
||||
fmt.Println("Updated deployment...")
|
||||
|
||||
// List Deployments
|
||||
prompt()
|
||||
fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault)
|
||||
list, err := client.Resource(deploymentRes).Namespace(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, d := range list.Items {
|
||||
replicas, found, err := unstructured.NestedInt64(d.Object, "spec", "replicas")
|
||||
if err != nil || !found {
|
||||
fmt.Printf("Replicas not found for deployment %s: error=%s", d.GetName(), err)
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" * %s (%d replicas)\n", d.GetName(), replicas)
|
||||
}
|
||||
|
||||
// Delete Deployment
|
||||
prompt()
|
||||
fmt.Println("Deleting deployment...")
|
||||
deletePolicy := metav1.DeletePropagationForeground
|
||||
deleteOptions := &metav1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
}
|
||||
if err := client.Resource(deploymentRes).Namespace(namespace).Delete("demo-deployment", deleteOptions); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println("Deleted deployment.")
|
||||
}
|
||||
|
||||
func prompt() {
|
||||
fmt.Printf("-> Press Return key to continue.")
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
break
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
29
go.mod
29
go.mod
@@ -8,38 +8,35 @@ require (
|
||||
github.com/Azure/go-autorest v11.1.2+incompatible
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda // indirect
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible
|
||||
github.com/gogo/protobuf v0.0.0-20190410021324-65acae22fc9
|
||||
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550
|
||||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903
|
||||
github.com/golang/protobuf v1.2.0
|
||||
github.com/google/btree v0.0.0-20160524151835-7d79101e329e // indirect
|
||||
github.com/google/gofuzz v1.0.0
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d
|
||||
github.com/gophercloud/gophercloud v0.1.0
|
||||
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7
|
||||
github.com/imdario/mergo v0.3.5
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/stretchr/testify v1.3.0
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980
|
||||
github.com/spf13/pflag v1.0.1
|
||||
github.com/stretchr/testify v1.2.2
|
||||
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
|
||||
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d
|
||||
google.golang.org/appengine v1.5.0 // indirect
|
||||
k8s.io/api v0.0.0-20190730183008-42d28c278e58
|
||||
k8s.io/apimachinery v0.0.0-20190727130956-f97a4e5b4abc
|
||||
k8s.io/api v0.0.0-20190819141256-463df2a5c347
|
||||
k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d
|
||||
k8s.io/klog v0.3.1
|
||||
k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a
|
||||
k8s.io/utils v0.0.0-20190221042446-c2654d5206da
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
)
|
||||
|
||||
replace (
|
||||
golang.org/x/crypto => golang.org/x/crypto v0.0.0-20181025213731-e84da0312774
|
||||
golang.org/x/net => golang.org/x/net v0.0.0-20190206173232-65e2d4e15006
|
||||
golang.org/x/sync => golang.org/x/sync v0.0.0-20181108010431-42b317875d0f
|
||||
golang.org/x/sys => golang.org/x/sys v0.0.0-20190209173611-3b5209105503
|
||||
golang.org/x/text => golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db
|
||||
golang.org/x/tools => golang.org/x/tools v0.0.0-20190313210603-aa82965741a9
|
||||
k8s.io/api => k8s.io/api v0.0.0-20190730183008-42d28c278e58
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190727130956-f97a4e5b4abc
|
||||
k8s.io/api => k8s.io/api v0.0.0-20190819141256-463df2a5c347
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d
|
||||
)
|
||||
|
||||
97
go.sum
97
go.sum
@@ -2,11 +2,6 @@ cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Azure/go-autorest v11.1.2+incompatible h1:viZ3tV5l4gE2Sw0xrasFHytCGtzYCrT+um/rrSQ1BfA=
|
||||
github.com/Azure/go-autorest v11.1.2+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
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/dgrijalva/jwt-go v0.0.0-20160705203006-01aeca54ebda h1:NyywMz59neOoVRFDz+ccfKWxn784fiHMDnZSy6T+JXY=
|
||||
@@ -15,36 +10,28 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QL
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e h1:p1yVGRW3nmb85p1Sh1ZJSDm4A4iKLS5QNbvUHMgGu/M=
|
||||
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
|
||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550 h1:mV9jbLoSW/8m4VK16ZkHTozJa8sesK5u5kTMFysTYac=
|
||||
github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/gogo/protobuf v0.0.0-20190410021324-65acae22fc9 h1:Kt4R9nQn1c+x/o63vCZuxo3WjBc8EnSfnguI4ELkdoo=
|
||||
github.com/gogo/protobuf v0.0.0-20190410021324-65acae22fc9/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415 h1:WSBJMqJbLxsn+bTCPyPYZfqHdJmc8MK4wrBjMft6BAM=
|
||||
github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/btree v0.0.0-20160524151835-7d79101e329e h1:JHB7F/4TJCrYBW8+GZO8VkWDj1jxcWuCl6uxKODiyi4=
|
||||
github.com/google/btree v0.0.0-20160524151835-7d79101e329e/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
|
||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gophercloud/gophercloud v0.1.0 h1:P/nh25+rzXouhytV2pUHBb65fnds26Ghl8/391+sT5o=
|
||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8 h1:L9JPKrtsHMQ4VCRQfHvbbHBfB2Urn8xf6QZeXZ+OrN4=
|
||||
github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:3WdhXV3rUYy9p6AUW8d94kr+HS62Y4VL9mBnFxsD8q4=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
|
||||
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
|
||||
@@ -53,55 +40,39 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.5 h1:JboBksRwiiAJWvIYJVo46AfV+IAIKZpfrSzVKj42R4Q=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be h1:AHimNtVIpiBjPUhEF5KNCkrUyqTSA5zWUl8sQ2bfGBE=
|
||||
github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
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-20180320133207-05fbef0ca5da/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/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
|
||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
|
||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3 h1:EooPXg51Tn+xmWPXJUGCnJhJSpeuMlBmfJVcqIRmmv8=
|
||||
github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
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/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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/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.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774 h1:a4tQYYYuK9QdeO/+kEvNYyuR21S+7ve5EANok6hABhI=
|
||||
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006 h1:bfLnR+k0tq5Lqt6dflRLcZiz6UaXCMt3vhYJ1l4FQ80=
|
||||
golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
|
||||
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a h1:tImsplftrFpALCYumobsd0K86vlAs/eXGFms2txfJfA=
|
||||
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f h1:Bl/8QSvNqXvPGPGXa2z5xUTmV7VDcZyvRZ+QQXkXTZQ=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg=
|
||||
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db h1:6/JqlYfC1CCaLnGceQTI+sDGhC9UBSPAsBqI0Gun6kU=
|
||||
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20161028155119-f51c12702a4d h1:TnM+PKb3ylGmZvyPXmo9m/wktg7Jn/a/fNmr33HSj8g=
|
||||
@@ -112,8 +83,6 @@ google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
|
||||
@@ -122,19 +91,13 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
k8s.io/api v0.0.0-20190730183008-42d28c278e58/go.mod h1:gGyif5Gpa+QY8+cR+LX2vnDTcfZpBYFmztKX91bN9IM=
|
||||
k8s.io/apimachinery v0.0.0-20190727130956-f97a4e5b4abc/go.mod h1:eXR4ljjmbwK6Ng0PKsXRySPXnTUy/qBUa6kPDeckhQ0=
|
||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
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/api v0.0.0-20190819141256-463df2a5c347/go.mod h1:AOxZTnaXR/xiarlQL0JUfwQPxjmKDvVYoRp58cA7lUo=
|
||||
k8s.io/apimachinery v0.0.0-20190817020851-f2f3a405f61d/go.mod h1:3jediapYqJ2w1BFw7lAZPCx7scubsTfosqHkhXCWJKw=
|
||||
k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68=
|
||||
k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058 h1:di3XCwddOR9cWBNpfgXaskhh6cgJuwcK54rvtwUaC10=
|
||||
k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4=
|
||||
k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a h1:2jUDc9gJja832Ftp+QbDV0tVhQHMISFn01els+2ZAcw=
|
||||
k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30 h1:TRb4wNWoBVrH9plmkp2q86FIDppkbrEXdXlxU3a3BMI=
|
||||
k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
|
||||
k8s.io/utils v0.0.0-20190221042446-c2654d5206da h1:ElyM7RPonbKnQqOcw7dG2IK5uvQQn3b/WPHqD5mBvP4=
|
||||
k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
||||
@@ -19,15 +19,12 @@ limitations under the License.
|
||||
package admissionregistration
|
||||
|
||||
import (
|
||||
v1 "k8s.io/client-go/informers/admissionregistration/v1"
|
||||
v1beta1 "k8s.io/client-go/informers/admissionregistration/v1beta1"
|
||||
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1 provides access to shared informers for resources in V1.
|
||||
V1() v1.Interface
|
||||
// V1beta1 provides access to shared informers for resources in V1beta1.
|
||||
V1beta1() v1beta1.Interface
|
||||
}
|
||||
@@ -43,11 +40,6 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1 returns a new v1.Interface.
|
||||
func (g *group) V1() v1.Interface {
|
||||
return v1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
||||
// V1beta1 returns a new v1beta1.Interface.
|
||||
func (g *group) V1beta1() v1beta1.Interface {
|
||||
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// MutatingWebhookConfigurations returns a MutatingWebhookConfigurationInformer.
|
||||
MutatingWebhookConfigurations() MutatingWebhookConfigurationInformer
|
||||
// ValidatingWebhookConfigurations returns a ValidatingWebhookConfigurationInformer.
|
||||
ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// MutatingWebhookConfigurations returns a MutatingWebhookConfigurationInformer.
|
||||
func (v *version) MutatingWebhookConfigurations() MutatingWebhookConfigurationInformer {
|
||||
return &mutatingWebhookConfigurationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// ValidatingWebhookConfigurations returns a ValidatingWebhookConfigurationInformer.
|
||||
func (v *version) ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInformer {
|
||||
return &validatingWebhookConfigurationInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
|
||||
kubernetes "k8s.io/client-go/kubernetes"
|
||||
v1 "k8s.io/client-go/listers/admissionregistration/v1"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// MutatingWebhookConfigurationInformer provides access to a shared informer and lister for
|
||||
// MutatingWebhookConfigurations.
|
||||
type MutatingWebhookConfigurationInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1.MutatingWebhookConfigurationLister
|
||||
}
|
||||
|
||||
type mutatingWebhookConfigurationInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// NewMutatingWebhookConfigurationInformer constructs a new informer for MutatingWebhookConfiguration type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewMutatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredMutatingWebhookConfigurationInformer(client, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredMutatingWebhookConfigurationInformer constructs a new informer for MutatingWebhookConfiguration type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredMutatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.AdmissionregistrationV1().MutatingWebhookConfigurations().List(options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.AdmissionregistrationV1().MutatingWebhookConfigurations().Watch(options)
|
||||
},
|
||||
},
|
||||
&admissionregistrationv1.MutatingWebhookConfiguration{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *mutatingWebhookConfigurationInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredMutatingWebhookConfigurationInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *mutatingWebhookConfigurationInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&admissionregistrationv1.MutatingWebhookConfiguration{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *mutatingWebhookConfigurationInformer) Lister() v1.MutatingWebhookConfigurationLister {
|
||||
return v1.NewMutatingWebhookConfigurationLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
|
||||
kubernetes "k8s.io/client-go/kubernetes"
|
||||
v1 "k8s.io/client-go/listers/admissionregistration/v1"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// ValidatingWebhookConfigurationInformer provides access to a shared informer and lister for
|
||||
// ValidatingWebhookConfigurations.
|
||||
type ValidatingWebhookConfigurationInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1.ValidatingWebhookConfigurationLister
|
||||
}
|
||||
|
||||
type validatingWebhookConfigurationInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// NewValidatingWebhookConfigurationInformer constructs a new informer for ValidatingWebhookConfiguration type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewValidatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredValidatingWebhookConfigurationInformer(client, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredValidatingWebhookConfigurationInformer constructs a new informer for ValidatingWebhookConfiguration type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredValidatingWebhookConfigurationInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.AdmissionregistrationV1().ValidatingWebhookConfigurations().List(options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.AdmissionregistrationV1().ValidatingWebhookConfigurations().Watch(options)
|
||||
},
|
||||
},
|
||||
&admissionregistrationv1.ValidatingWebhookConfiguration{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *validatingWebhookConfigurationInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredValidatingWebhookConfigurationInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *validatingWebhookConfigurationInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&admissionregistrationv1.ValidatingWebhookConfiguration{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *validatingWebhookConfigurationInformer) Lister() v1.ValidatingWebhookConfigurationLister {
|
||||
return v1.NewValidatingWebhookConfigurationLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -21,9 +21,8 @@ package informers
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
v1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
v1beta2 "k8s.io/api/apps/v1beta2"
|
||||
v1alpha1 "k8s.io/api/auditregistration/v1alpha1"
|
||||
@@ -84,28 +83,22 @@ func (f *genericInformer) Lister() cache.GenericLister {
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=admissionregistration.k8s.io, Version=v1
|
||||
case v1.SchemeGroupVersion.WithResource("mutatingwebhookconfigurations"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Admissionregistration().V1().MutatingWebhookConfigurations().Informer()}, nil
|
||||
case v1.SchemeGroupVersion.WithResource("validatingwebhookconfigurations"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Admissionregistration().V1().ValidatingWebhookConfigurations().Informer()}, nil
|
||||
|
||||
// Group=admissionregistration.k8s.io, Version=v1beta1
|
||||
// Group=admissionregistration.k8s.io, Version=v1beta1
|
||||
case v1beta1.SchemeGroupVersion.WithResource("mutatingwebhookconfigurations"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Admissionregistration().V1beta1().MutatingWebhookConfigurations().Informer()}, nil
|
||||
case v1beta1.SchemeGroupVersion.WithResource("validatingwebhookconfigurations"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Admissionregistration().V1beta1().ValidatingWebhookConfigurations().Informer()}, nil
|
||||
|
||||
// Group=apps, Version=v1
|
||||
case appsv1.SchemeGroupVersion.WithResource("controllerrevisions"):
|
||||
case v1.SchemeGroupVersion.WithResource("controllerrevisions"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1().ControllerRevisions().Informer()}, nil
|
||||
case appsv1.SchemeGroupVersion.WithResource("daemonsets"):
|
||||
case v1.SchemeGroupVersion.WithResource("daemonsets"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1().DaemonSets().Informer()}, nil
|
||||
case appsv1.SchemeGroupVersion.WithResource("deployments"):
|
||||
case v1.SchemeGroupVersion.WithResource("deployments"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1().Deployments().Informer()}, nil
|
||||
case appsv1.SchemeGroupVersion.WithResource("replicasets"):
|
||||
case v1.SchemeGroupVersion.WithResource("replicasets"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1().ReplicaSets().Informer()}, nil
|
||||
case appsv1.SchemeGroupVersion.WithResource("statefulsets"):
|
||||
case v1.SchemeGroupVersion.WithResource("statefulsets"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apps().V1().StatefulSets().Informer()}, nil
|
||||
|
||||
// Group=apps, Version=v1beta1
|
||||
|
||||
@@ -19,10 +19,7 @@ limitations under the License.
|
||||
package kubernetes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
admissionregistrationv1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1"
|
||||
admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
appsv1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
|
||||
@@ -65,7 +62,6 @@ import (
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
AdmissionregistrationV1() admissionregistrationv1.AdmissionregistrationV1Interface
|
||||
AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface
|
||||
AppsV1() appsv1.AppsV1Interface
|
||||
AppsV1beta1() appsv1beta1.AppsV1beta1Interface
|
||||
@@ -108,7 +104,6 @@ type Interface interface {
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
admissionregistrationV1 *admissionregistrationv1.AdmissionregistrationV1Client
|
||||
admissionregistrationV1beta1 *admissionregistrationv1beta1.AdmissionregistrationV1beta1Client
|
||||
appsV1 *appsv1.AppsV1Client
|
||||
appsV1beta1 *appsv1beta1.AppsV1beta1Client
|
||||
@@ -147,11 +142,6 @@ type Clientset struct {
|
||||
storageV1alpha1 *storagev1alpha1.StorageV1alpha1Client
|
||||
}
|
||||
|
||||
// AdmissionregistrationV1 retrieves the AdmissionregistrationV1Client
|
||||
func (c *Clientset) AdmissionregistrationV1() admissionregistrationv1.AdmissionregistrationV1Interface {
|
||||
return c.admissionregistrationV1
|
||||
}
|
||||
|
||||
// AdmissionregistrationV1beta1 retrieves the AdmissionregistrationV1beta1Client
|
||||
func (c *Clientset) AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface {
|
||||
return c.admissionregistrationV1beta1
|
||||
@@ -341,22 +331,13 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
if configShallowCopy.Burst <= 0 {
|
||||
return nil, fmt.Errorf("Burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||
}
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.admissionregistrationV1, err = admissionregistrationv1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cs.admissionregistrationV1beta1, err = admissionregistrationv1beta1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -513,7 +494,6 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.admissionregistrationV1 = admissionregistrationv1.NewForConfigOrDie(c)
|
||||
cs.admissionregistrationV1beta1 = admissionregistrationv1beta1.NewForConfigOrDie(c)
|
||||
cs.appsV1 = appsv1.NewForConfigOrDie(c)
|
||||
cs.appsV1beta1 = appsv1beta1.NewForConfigOrDie(c)
|
||||
@@ -558,7 +538,6 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.admissionregistrationV1 = admissionregistrationv1.New(c)
|
||||
cs.admissionregistrationV1beta1 = admissionregistrationv1beta1.New(c)
|
||||
cs.appsV1 = appsv1.New(c)
|
||||
cs.appsV1beta1 = appsv1beta1.New(c)
|
||||
|
||||
@@ -24,8 +24,6 @@ import (
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
admissionregistrationv1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1"
|
||||
fakeadmissionregistrationv1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1/fake"
|
||||
admissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1"
|
||||
fakeadmissionregistrationv1beta1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1/fake"
|
||||
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
|
||||
@@ -148,11 +146,6 @@ func (c *Clientset) Tracker() testing.ObjectTracker {
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// AdmissionregistrationV1 retrieves the AdmissionregistrationV1Client
|
||||
func (c *Clientset) AdmissionregistrationV1() admissionregistrationv1.AdmissionregistrationV1Interface {
|
||||
return &fakeadmissionregistrationv1.FakeAdmissionregistrationV1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// AdmissionregistrationV1beta1 retrieves the AdmissionregistrationV1beta1Client
|
||||
func (c *Clientset) AdmissionregistrationV1beta1() admissionregistrationv1beta1.AdmissionregistrationV1beta1Interface {
|
||||
return &fakeadmissionregistrationv1beta1.FakeAdmissionregistrationV1beta1{Fake: &c.Fake}
|
||||
|
||||
@@ -19,7 +19,6 @@ limitations under the License.
|
||||
package fake
|
||||
|
||||
import (
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
@@ -67,7 +66,6 @@ var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
admissionregistrationv1.AddToScheme,
|
||||
admissionregistrationv1beta1.AddToScheme,
|
||||
appsv1.AddToScheme,
|
||||
appsv1beta1.AddToScheme,
|
||||
|
||||
@@ -19,7 +19,6 @@ limitations under the License.
|
||||
package scheme
|
||||
|
||||
import (
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
appsv1beta1 "k8s.io/api/apps/v1beta1"
|
||||
@@ -67,7 +66,6 @@ var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
admissionregistrationv1.AddToScheme,
|
||||
admissionregistrationv1beta1.AddToScheme,
|
||||
appsv1.AddToScheme,
|
||||
appsv1beta1.AddToScheme,
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type AdmissionregistrationV1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
MutatingWebhookConfigurationsGetter
|
||||
ValidatingWebhookConfigurationsGetter
|
||||
}
|
||||
|
||||
// AdmissionregistrationV1Client is used to interact with features provided by the admissionregistration.k8s.io group.
|
||||
type AdmissionregistrationV1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *AdmissionregistrationV1Client) MutatingWebhookConfigurations() MutatingWebhookConfigurationInterface {
|
||||
return newMutatingWebhookConfigurations(c)
|
||||
}
|
||||
|
||||
func (c *AdmissionregistrationV1Client) ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInterface {
|
||||
return newValidatingWebhookConfigurations(c)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new AdmissionregistrationV1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*AdmissionregistrationV1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &AdmissionregistrationV1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new AdmissionregistrationV1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *AdmissionregistrationV1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new AdmissionregistrationV1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *AdmissionregistrationV1Client {
|
||||
return &AdmissionregistrationV1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *AdmissionregistrationV1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "k8s.io/client-go/kubernetes/typed/admissionregistration/v1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeAdmissionregistrationV1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeAdmissionregistrationV1) MutatingWebhookConfigurations() v1.MutatingWebhookConfigurationInterface {
|
||||
return &FakeMutatingWebhookConfigurations{c}
|
||||
}
|
||||
|
||||
func (c *FakeAdmissionregistrationV1) ValidatingWebhookConfigurations() v1.ValidatingWebhookConfigurationInterface {
|
||||
return &FakeValidatingWebhookConfigurations{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeAdmissionregistrationV1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeMutatingWebhookConfigurations implements MutatingWebhookConfigurationInterface
|
||||
type FakeMutatingWebhookConfigurations struct {
|
||||
Fake *FakeAdmissionregistrationV1
|
||||
}
|
||||
|
||||
var mutatingwebhookconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1", Resource: "mutatingwebhookconfigurations"}
|
||||
|
||||
var mutatingwebhookconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1", Kind: "MutatingWebhookConfiguration"}
|
||||
|
||||
// Get takes name of the mutatingWebhookConfiguration, and returns the corresponding mutatingWebhookConfiguration object, and an error if there is any.
|
||||
func (c *FakeMutatingWebhookConfigurations) Get(name string, options v1.GetOptions) (result *admissionregistrationv1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(mutatingwebhookconfigurationsResource, name), &admissionregistrationv1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of MutatingWebhookConfigurations that match those selectors.
|
||||
func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *admissionregistrationv1.MutatingWebhookConfigurationList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(mutatingwebhookconfigurationsResource, mutatingwebhookconfigurationsKind, opts), &admissionregistrationv1.MutatingWebhookConfigurationList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &admissionregistrationv1.MutatingWebhookConfigurationList{ListMeta: obj.(*admissionregistrationv1.MutatingWebhookConfigurationList).ListMeta}
|
||||
for _, item := range obj.(*admissionregistrationv1.MutatingWebhookConfigurationList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested mutatingWebhookConfigurations.
|
||||
func (c *FakeMutatingWebhookConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(mutatingwebhookconfigurationsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a mutatingWebhookConfiguration and creates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeMutatingWebhookConfigurations) Create(mutatingWebhookConfiguration *admissionregistrationv1.MutatingWebhookConfiguration) (result *admissionregistrationv1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(mutatingwebhookconfigurationsResource, mutatingWebhookConfiguration), &admissionregistrationv1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a mutatingWebhookConfiguration and updates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeMutatingWebhookConfigurations) Update(mutatingWebhookConfiguration *admissionregistrationv1.MutatingWebhookConfiguration) (result *admissionregistrationv1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(mutatingwebhookconfigurationsResource, mutatingWebhookConfiguration), &admissionregistrationv1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Delete takes name of the mutatingWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeMutatingWebhookConfigurations) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(mutatingwebhookconfigurationsResource, name), &admissionregistrationv1.MutatingWebhookConfiguration{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeMutatingWebhookConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(mutatingwebhookconfigurationsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &admissionregistrationv1.MutatingWebhookConfigurationList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched mutatingWebhookConfiguration.
|
||||
func (c *FakeMutatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *admissionregistrationv1.MutatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(mutatingwebhookconfigurationsResource, name, pt, data, subresources...), &admissionregistrationv1.MutatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.MutatingWebhookConfiguration), err
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeValidatingWebhookConfigurations implements ValidatingWebhookConfigurationInterface
|
||||
type FakeValidatingWebhookConfigurations struct {
|
||||
Fake *FakeAdmissionregistrationV1
|
||||
}
|
||||
|
||||
var validatingwebhookconfigurationsResource = schema.GroupVersionResource{Group: "admissionregistration.k8s.io", Version: "v1", Resource: "validatingwebhookconfigurations"}
|
||||
|
||||
var validatingwebhookconfigurationsKind = schema.GroupVersionKind{Group: "admissionregistration.k8s.io", Version: "v1", Kind: "ValidatingWebhookConfiguration"}
|
||||
|
||||
// Get takes name of the validatingWebhookConfiguration, and returns the corresponding validatingWebhookConfiguration object, and an error if there is any.
|
||||
func (c *FakeValidatingWebhookConfigurations) Get(name string, options v1.GetOptions) (result *admissionregistrationv1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(validatingwebhookconfigurationsResource, name), &admissionregistrationv1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ValidatingWebhookConfigurations that match those selectors.
|
||||
func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result *admissionregistrationv1.ValidatingWebhookConfigurationList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(validatingwebhookconfigurationsResource, validatingwebhookconfigurationsKind, opts), &admissionregistrationv1.ValidatingWebhookConfigurationList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &admissionregistrationv1.ValidatingWebhookConfigurationList{ListMeta: obj.(*admissionregistrationv1.ValidatingWebhookConfigurationList).ListMeta}
|
||||
for _, item := range obj.(*admissionregistrationv1.ValidatingWebhookConfigurationList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested validatingWebhookConfigurations.
|
||||
func (c *FakeValidatingWebhookConfigurations) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(validatingwebhookconfigurationsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a validatingWebhookConfiguration and creates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeValidatingWebhookConfigurations) Create(validatingWebhookConfiguration *admissionregistrationv1.ValidatingWebhookConfiguration) (result *admissionregistrationv1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(validatingwebhookconfigurationsResource, validatingWebhookConfiguration), &admissionregistrationv1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a validatingWebhookConfiguration and updates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *FakeValidatingWebhookConfigurations) Update(validatingWebhookConfiguration *admissionregistrationv1.ValidatingWebhookConfiguration) (result *admissionregistrationv1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(validatingwebhookconfigurationsResource, validatingWebhookConfiguration), &admissionregistrationv1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
|
||||
// Delete takes name of the validatingWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeValidatingWebhookConfigurations) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(validatingwebhookconfigurationsResource, name), &admissionregistrationv1.ValidatingWebhookConfiguration{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeValidatingWebhookConfigurations) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(validatingwebhookconfigurationsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &admissionregistrationv1.ValidatingWebhookConfigurationList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched validatingWebhookConfiguration.
|
||||
func (c *FakeValidatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *admissionregistrationv1.ValidatingWebhookConfiguration, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(validatingwebhookconfigurationsResource, name, pt, data, subresources...), &admissionregistrationv1.ValidatingWebhookConfiguration{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*admissionregistrationv1.ValidatingWebhookConfiguration), err
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
type MutatingWebhookConfigurationExpansion interface{}
|
||||
|
||||
type ValidatingWebhookConfigurationExpansion interface{}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
scheme "k8s.io/client-go/kubernetes/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// MutatingWebhookConfigurationsGetter has a method to return a MutatingWebhookConfigurationInterface.
|
||||
// A group's client should implement this interface.
|
||||
type MutatingWebhookConfigurationsGetter interface {
|
||||
MutatingWebhookConfigurations() MutatingWebhookConfigurationInterface
|
||||
}
|
||||
|
||||
// MutatingWebhookConfigurationInterface has methods to work with MutatingWebhookConfiguration resources.
|
||||
type MutatingWebhookConfigurationInterface interface {
|
||||
Create(*v1.MutatingWebhookConfiguration) (*v1.MutatingWebhookConfiguration, error)
|
||||
Update(*v1.MutatingWebhookConfiguration) (*v1.MutatingWebhookConfiguration, error)
|
||||
Delete(name string, options *metav1.DeleteOptions) error
|
||||
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
||||
Get(name string, options metav1.GetOptions) (*v1.MutatingWebhookConfiguration, error)
|
||||
List(opts metav1.ListOptions) (*v1.MutatingWebhookConfigurationList, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.MutatingWebhookConfiguration, err error)
|
||||
MutatingWebhookConfigurationExpansion
|
||||
}
|
||||
|
||||
// mutatingWebhookConfigurations implements MutatingWebhookConfigurationInterface
|
||||
type mutatingWebhookConfigurations struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newMutatingWebhookConfigurations returns a MutatingWebhookConfigurations
|
||||
func newMutatingWebhookConfigurations(c *AdmissionregistrationV1Client) *mutatingWebhookConfigurations {
|
||||
return &mutatingWebhookConfigurations{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the mutatingWebhookConfiguration, and returns the corresponding mutatingWebhookConfiguration object, and an error if there is any.
|
||||
func (c *mutatingWebhookConfigurations) Get(name string, options metav1.GetOptions) (result *v1.MutatingWebhookConfiguration, err error) {
|
||||
result = &v1.MutatingWebhookConfiguration{}
|
||||
err = c.client.Get().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of MutatingWebhookConfigurations that match those selectors.
|
||||
func (c *mutatingWebhookConfigurations) List(opts metav1.ListOptions) (result *v1.MutatingWebhookConfigurationList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1.MutatingWebhookConfigurationList{}
|
||||
err = c.client.Get().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested mutatingWebhookConfigurations.
|
||||
func (c *mutatingWebhookConfigurations) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a mutatingWebhookConfiguration and creates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *mutatingWebhookConfigurations) Create(mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration) (result *v1.MutatingWebhookConfiguration, err error) {
|
||||
result = &v1.MutatingWebhookConfiguration{}
|
||||
err = c.client.Post().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
Body(mutatingWebhookConfiguration).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a mutatingWebhookConfiguration and updates it. Returns the server's representation of the mutatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *mutatingWebhookConfigurations) Update(mutatingWebhookConfiguration *v1.MutatingWebhookConfiguration) (result *v1.MutatingWebhookConfiguration, err error) {
|
||||
result = &v1.MutatingWebhookConfiguration{}
|
||||
err = c.client.Put().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
Name(mutatingWebhookConfiguration.Name).
|
||||
Body(mutatingWebhookConfiguration).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the mutatingWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *mutatingWebhookConfigurations) Delete(name string, options *metav1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *mutatingWebhookConfigurations) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOptions.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched mutatingWebhookConfiguration.
|
||||
func (c *mutatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.MutatingWebhookConfiguration, err error) {
|
||||
result = &v1.MutatingWebhookConfiguration{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("mutatingwebhookconfigurations").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
scheme "k8s.io/client-go/kubernetes/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// ValidatingWebhookConfigurationsGetter has a method to return a ValidatingWebhookConfigurationInterface.
|
||||
// A group's client should implement this interface.
|
||||
type ValidatingWebhookConfigurationsGetter interface {
|
||||
ValidatingWebhookConfigurations() ValidatingWebhookConfigurationInterface
|
||||
}
|
||||
|
||||
// ValidatingWebhookConfigurationInterface has methods to work with ValidatingWebhookConfiguration resources.
|
||||
type ValidatingWebhookConfigurationInterface interface {
|
||||
Create(*v1.ValidatingWebhookConfiguration) (*v1.ValidatingWebhookConfiguration, error)
|
||||
Update(*v1.ValidatingWebhookConfiguration) (*v1.ValidatingWebhookConfiguration, error)
|
||||
Delete(name string, options *metav1.DeleteOptions) error
|
||||
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
||||
Get(name string, options metav1.GetOptions) (*v1.ValidatingWebhookConfiguration, error)
|
||||
List(opts metav1.ListOptions) (*v1.ValidatingWebhookConfigurationList, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ValidatingWebhookConfiguration, err error)
|
||||
ValidatingWebhookConfigurationExpansion
|
||||
}
|
||||
|
||||
// validatingWebhookConfigurations implements ValidatingWebhookConfigurationInterface
|
||||
type validatingWebhookConfigurations struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newValidatingWebhookConfigurations returns a ValidatingWebhookConfigurations
|
||||
func newValidatingWebhookConfigurations(c *AdmissionregistrationV1Client) *validatingWebhookConfigurations {
|
||||
return &validatingWebhookConfigurations{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the validatingWebhookConfiguration, and returns the corresponding validatingWebhookConfiguration object, and an error if there is any.
|
||||
func (c *validatingWebhookConfigurations) Get(name string, options metav1.GetOptions) (result *v1.ValidatingWebhookConfiguration, err error) {
|
||||
result = &v1.ValidatingWebhookConfiguration{}
|
||||
err = c.client.Get().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of ValidatingWebhookConfigurations that match those selectors.
|
||||
func (c *validatingWebhookConfigurations) List(opts metav1.ListOptions) (result *v1.ValidatingWebhookConfigurationList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1.ValidatingWebhookConfigurationList{}
|
||||
err = c.client.Get().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested validatingWebhookConfigurations.
|
||||
func (c *validatingWebhookConfigurations) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a validatingWebhookConfiguration and creates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *validatingWebhookConfigurations) Create(validatingWebhookConfiguration *v1.ValidatingWebhookConfiguration) (result *v1.ValidatingWebhookConfiguration, err error) {
|
||||
result = &v1.ValidatingWebhookConfiguration{}
|
||||
err = c.client.Post().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
Body(validatingWebhookConfiguration).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a validatingWebhookConfiguration and updates it. Returns the server's representation of the validatingWebhookConfiguration, and an error, if there is any.
|
||||
func (c *validatingWebhookConfigurations) Update(validatingWebhookConfiguration *v1.ValidatingWebhookConfiguration) (result *v1.ValidatingWebhookConfiguration, err error) {
|
||||
result = &v1.ValidatingWebhookConfiguration{}
|
||||
err = c.client.Put().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
Name(validatingWebhookConfiguration.Name).
|
||||
Body(validatingWebhookConfiguration).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the validatingWebhookConfiguration and deletes it. Returns an error if one occurs.
|
||||
func (c *validatingWebhookConfigurations) Delete(name string, options *metav1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *validatingWebhookConfigurations) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOptions.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Resource("validatingwebhookconfigurations").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched validatingWebhookConfiguration.
|
||||
func (c *validatingWebhookConfigurations) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.ValidatingWebhookConfiguration, err error) {
|
||||
result = &v1.ValidatingWebhookConfiguration{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("validatingwebhookconfigurations").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
@@ -138,25 +138,3 @@ func (c *FakePods) Patch(name string, pt types.PatchType, data []byte, subresour
|
||||
}
|
||||
return obj.(*corev1.Pod), err
|
||||
}
|
||||
|
||||
// GetEphemeralContainers takes name of the pod, and returns the corresponding ephemeralContainers object, and an error if there is any.
|
||||
func (c *FakePods) GetEphemeralContainers(podName string, options v1.GetOptions) (result *corev1.EphemeralContainers, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetSubresourceAction(podsResource, c.ns, "ephemeralcontainers", podName), &corev1.EphemeralContainers{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*corev1.EphemeralContainers), err
|
||||
}
|
||||
|
||||
// UpdateEphemeralContainers takes the representation of a ephemeralContainers and updates it. Returns the server's representation of the ephemeralContainers, and an error, if there is any.
|
||||
func (c *FakePods) UpdateEphemeralContainers(podName string, ephemeralContainers *corev1.EphemeralContainers) (result *corev1.EphemeralContainers, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(podsResource, "ephemeralcontainers", c.ns, ephemeralContainers), &corev1.EphemeralContainers{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*corev1.EphemeralContainers), err
|
||||
}
|
||||
|
||||
@@ -46,9 +46,6 @@ type PodInterface interface {
|
||||
List(opts metav1.ListOptions) (*v1.PodList, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Pod, err error)
|
||||
GetEphemeralContainers(podName string, options metav1.GetOptions) (*v1.EphemeralContainers, error)
|
||||
UpdateEphemeralContainers(podName string, ephemeralContainers *v1.EphemeralContainers) (*v1.EphemeralContainers, error)
|
||||
|
||||
PodExpansion
|
||||
}
|
||||
|
||||
@@ -192,31 +189,3 @@ func (c *pods) Patch(name string, pt types.PatchType, data []byte, subresources
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// GetEphemeralContainers takes name of the pod, and returns the corresponding v1.EphemeralContainers object, and an error if there is any.
|
||||
func (c *pods) GetEphemeralContainers(podName string, options metav1.GetOptions) (result *v1.EphemeralContainers, err error) {
|
||||
result = &v1.EphemeralContainers{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("pods").
|
||||
Name(podName).
|
||||
SubResource("ephemeralcontainers").
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateEphemeralContainers takes the top resource name and the representation of a ephemeralContainers and updates it. Returns the server's representation of the ephemeralContainers, and an error, if there is any.
|
||||
func (c *pods) UpdateEphemeralContainers(podName string, ephemeralContainers *v1.EphemeralContainers) (result *v1.EphemeralContainers, err error) {
|
||||
result = &v1.EphemeralContainers{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("pods").
|
||||
Name(podName).
|
||||
SubResource("ephemeralcontainers").
|
||||
Body(ephemeralContainers).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes Authors.
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// MutatingWebhookConfigurationListerExpansion allows custom methods to be added to
|
||||
// MutatingWebhookConfigurationLister.
|
||||
type MutatingWebhookConfigurationListerExpansion interface{}
|
||||
|
||||
// ValidatingWebhookConfigurationListerExpansion allows custom methods to be added to
|
||||
// ValidatingWebhookConfigurationLister.
|
||||
type ValidatingWebhookConfigurationListerExpansion interface{}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// MutatingWebhookConfigurationLister helps list MutatingWebhookConfigurations.
|
||||
type MutatingWebhookConfigurationLister interface {
|
||||
// List lists all MutatingWebhookConfigurations in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1.MutatingWebhookConfiguration, err error)
|
||||
// Get retrieves the MutatingWebhookConfiguration from the index for a given name.
|
||||
Get(name string) (*v1.MutatingWebhookConfiguration, error)
|
||||
MutatingWebhookConfigurationListerExpansion
|
||||
}
|
||||
|
||||
// mutatingWebhookConfigurationLister implements the MutatingWebhookConfigurationLister interface.
|
||||
type mutatingWebhookConfigurationLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewMutatingWebhookConfigurationLister returns a new MutatingWebhookConfigurationLister.
|
||||
func NewMutatingWebhookConfigurationLister(indexer cache.Indexer) MutatingWebhookConfigurationLister {
|
||||
return &mutatingWebhookConfigurationLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all MutatingWebhookConfigurations in the indexer.
|
||||
func (s *mutatingWebhookConfigurationLister) List(selector labels.Selector) (ret []*v1.MutatingWebhookConfiguration, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1.MutatingWebhookConfiguration))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the MutatingWebhookConfiguration from the index for a given name.
|
||||
func (s *mutatingWebhookConfigurationLister) Get(name string) (*v1.MutatingWebhookConfiguration, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1.Resource("mutatingwebhookconfiguration"), name)
|
||||
}
|
||||
return obj.(*v1.MutatingWebhookConfiguration), nil
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// ValidatingWebhookConfigurationLister helps list ValidatingWebhookConfigurations.
|
||||
type ValidatingWebhookConfigurationLister interface {
|
||||
// List lists all ValidatingWebhookConfigurations in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1.ValidatingWebhookConfiguration, err error)
|
||||
// Get retrieves the ValidatingWebhookConfiguration from the index for a given name.
|
||||
Get(name string) (*v1.ValidatingWebhookConfiguration, error)
|
||||
ValidatingWebhookConfigurationListerExpansion
|
||||
}
|
||||
|
||||
// validatingWebhookConfigurationLister implements the ValidatingWebhookConfigurationLister interface.
|
||||
type validatingWebhookConfigurationLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewValidatingWebhookConfigurationLister returns a new ValidatingWebhookConfigurationLister.
|
||||
func NewValidatingWebhookConfigurationLister(indexer cache.Indexer) ValidatingWebhookConfigurationLister {
|
||||
return &validatingWebhookConfigurationLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all ValidatingWebhookConfigurations in the indexer.
|
||||
func (s *validatingWebhookConfigurationLister) List(selector labels.Selector) (ret []*v1.ValidatingWebhookConfiguration, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1.ValidatingWebhookConfiguration))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the ValidatingWebhookConfiguration from the index for a given name.
|
||||
func (s *validatingWebhookConfigurationLister) Get(name string) (*v1.ValidatingWebhookConfiguration, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1.Resource("validatingwebhookconfiguration"), name)
|
||||
}
|
||||
return obj.(*v1.ValidatingWebhookConfiguration), nil
|
||||
}
|
||||
@@ -1,390 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 fake
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/metadata"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// MetadataClient assists in creating fake objects for use when testing, since metadata.Getter
|
||||
// does not expose create
|
||||
type MetadataClient interface {
|
||||
metadata.Getter
|
||||
CreateFake(obj *metav1.PartialObjectMetadata, opts metav1.CreateOptions, subresources ...string) (*metav1.PartialObjectMetadata, error)
|
||||
UpdateFake(obj *metav1.PartialObjectMetadata, opts metav1.UpdateOptions, subresources ...string) (*metav1.PartialObjectMetadata, error)
|
||||
}
|
||||
|
||||
// NewSimpleMetadataClient creates a new client that will use the provided scheme and respond with the
|
||||
// provided objects when requests are made. It will track actions made to the client which can be checked
|
||||
// with GetActions().
|
||||
func NewSimpleMetadataClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeMetadataClient {
|
||||
gvkFakeList := schema.GroupVersionKind{Group: "fake-metadata-client-group", Version: "v1", Kind: "List"}
|
||||
if !scheme.Recognizes(gvkFakeList) {
|
||||
// In order to use List with this client, you have to have the v1.List registered in your scheme, since this is a test
|
||||
// type we modify the input scheme
|
||||
scheme.AddKnownTypeWithName(gvkFakeList, &metav1.List{})
|
||||
}
|
||||
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDeserializer())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &FakeMetadataClient{scheme: scheme}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// FakeMetadataClient implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type FakeMetadataClient struct {
|
||||
testing.Fake
|
||||
scheme *runtime.Scheme
|
||||
}
|
||||
|
||||
type metadataResourceClient struct {
|
||||
client *FakeMetadataClient
|
||||
namespace string
|
||||
resource schema.GroupVersionResource
|
||||
}
|
||||
|
||||
var _ metadata.Interface = &FakeMetadataClient{}
|
||||
|
||||
// Resource returns an interface for accessing the provided resource.
|
||||
func (c *FakeMetadataClient) Resource(resource schema.GroupVersionResource) metadata.Getter {
|
||||
return &metadataResourceClient{client: c, resource: resource}
|
||||
}
|
||||
|
||||
// Namespace returns an interface for accessing the current resource in the specified
|
||||
// namespace.
|
||||
func (c *metadataResourceClient) Namespace(ns string) metadata.ResourceInterface {
|
||||
ret := *c
|
||||
ret.namespace = ns
|
||||
return &ret
|
||||
}
|
||||
|
||||
// CreateFake records the object creation and processes it via the reactor.
|
||||
func (c *metadataResourceClient) CreateFake(obj *metav1.PartialObjectMetadata, opts metav1.CreateOptions, subresources ...string) (*metav1.PartialObjectMetadata, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootCreateAction(c.resource, obj), obj)
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := accessor.GetName()
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
name := accessor.GetName()
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewCreateSubresourceAction(c.resource, name, strings.Join(subresources, "/"), c.namespace, obj), obj)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, ok := uncastRet.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected return value type %T", uncastRet)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// UpdateFake records the object update and processes it via the reactor.
|
||||
func (c *metadataResourceClient) UpdateFake(obj *metav1.PartialObjectMetadata, opts metav1.UpdateOptions, subresources ...string) (*metav1.PartialObjectMetadata, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(c.resource, obj), obj)
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj)
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, obj), obj)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, ok := uncastRet.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected return value type %T", uncastRet)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// UpdateStatus records the object status update and processes it via the reactor.
|
||||
func (c *metadataResourceClient) UpdateStatus(obj *metav1.PartialObjectMetadata, opts metav1.UpdateOptions) (*metav1.PartialObjectMetadata, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(c.resource, "status", obj), obj)
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj)
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, ok := uncastRet.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected return value type %T", uncastRet)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Delete records the object deletion and processes it via the reactor.
|
||||
func (c *metadataResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(c.resource, name), &metav1.Status{Status: "metadata delete fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewRootDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "metadata delete fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "metadata delete fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
_, err = c.client.Fake.
|
||||
Invokes(testing.NewDeleteSubresourceAction(c.resource, strings.Join(subresources, "/"), c.namespace, name), &metav1.Status{Status: "metadata delete fail"})
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection records the object collection deletion and processes it via the reactor.
|
||||
func (c *metadataResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
action := testing.NewRootDeleteCollectionAction(c.resource, listOptions)
|
||||
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "metadata deletecollection fail"})
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
|
||||
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "metadata deletecollection fail"})
|
||||
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Get records the object retrieval and processes it via the reactor.
|
||||
func (c *metadataResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*metav1.PartialObjectMetadata, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootGetAction(c.resource, name), &metav1.Status{Status: "metadata get fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootGetSubresourceAction(c.resource, strings.Join(subresources, "/"), name), &metav1.Status{Status: "metadata get fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "metadata get fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewGetSubresourceAction(c.resource, c.namespace, strings.Join(subresources, "/"), name), &metav1.Status{Status: "metadata get fail"})
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, ok := uncastRet.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected return value type %T", uncastRet)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// List records the object deletion and processes it via the reactor.
|
||||
func (c *metadataResourceClient) List(opts metav1.ListOptions) (*metav1.PartialObjectMetadataList, error) {
|
||||
var obj runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
obj, err = c.client.Fake.
|
||||
Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Group: "fake-metadata-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, opts), &metav1.Status{Status: "metadata list fail"})
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
obj, err = c.client.Fake.
|
||||
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Group: "fake-metadata-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, c.namespace, opts), &metav1.Status{Status: "metadata list fail"})
|
||||
|
||||
}
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
|
||||
inputList, ok := obj.(*metav1.List)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("incoming object is incorrect type %T", obj)
|
||||
}
|
||||
fmt.Printf("DEBUG: %#v\n", inputList)
|
||||
|
||||
list := &metav1.PartialObjectMetadataList{
|
||||
ListMeta: inputList.ListMeta,
|
||||
}
|
||||
for i := range inputList.Items {
|
||||
item, ok := inputList.Items[i].Object.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("item %d in list %T is %T", i, inputList, inputList.Items[i].Object)
|
||||
}
|
||||
metadata, err := meta.Accessor(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if label.Matches(labels.Set(metadata.GetLabels())) {
|
||||
list.Items = append(list.Items, *item)
|
||||
}
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (c *metadataResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
switch {
|
||||
case len(c.namespace) == 0:
|
||||
return c.client.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(c.resource, opts))
|
||||
|
||||
case len(c.namespace) > 0:
|
||||
return c.client.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts))
|
||||
|
||||
}
|
||||
|
||||
panic("math broke")
|
||||
}
|
||||
|
||||
// Patch records the object patch and processes it via the reactor.
|
||||
func (c *metadataResourceClient) Patch(name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*metav1.PartialObjectMetadata, error) {
|
||||
var uncastRet runtime.Object
|
||||
var err error
|
||||
switch {
|
||||
case len(c.namespace) == 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchAction(c.resource, name, pt, data), &metav1.Status{Status: "metadata patch fail"})
|
||||
|
||||
case len(c.namespace) == 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, pt, data, subresources...), &metav1.Status{Status: "metadata patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) == 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchAction(c.resource, c.namespace, name, pt, data), &metav1.Status{Status: "metadata patch fail"})
|
||||
|
||||
case len(c.namespace) > 0 && len(subresources) > 0:
|
||||
uncastRet, err = c.client.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, pt, data, subresources...), &metav1.Status{Status: "metadata patch fail"})
|
||||
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uncastRet == nil {
|
||||
return nil, err
|
||||
}
|
||||
ret, ok := uncastRet.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected return value type %T", uncastRet)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 fake
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
)
|
||||
|
||||
const (
|
||||
testGroup = "testgroup"
|
||||
testVersion = "testversion"
|
||||
testResource = "testkinds"
|
||||
testNamespace = "testns"
|
||||
testName = "testname"
|
||||
testKind = "TestKind"
|
||||
testAPIVersion = "testgroup/testversion"
|
||||
)
|
||||
|
||||
var scheme *runtime.Scheme
|
||||
|
||||
func init() {
|
||||
scheme = runtime.NewScheme()
|
||||
metav1.AddMetaToScheme(scheme)
|
||||
}
|
||||
|
||||
func newPartialObjectMetadata(apiVersion, kind, namespace, name string) *metav1.PartialObjectMetadata {
|
||||
return &metav1.PartialObjectMetadata{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: apiVersion,
|
||||
Kind: kind,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newPartialObjectMetadataWithAnnotations(annotations map[string]string) *metav1.PartialObjectMetadata {
|
||||
u := newPartialObjectMetadata(testAPIVersion, testKind, testNamespace, testName)
|
||||
u.Annotations = annotations
|
||||
return u
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
client := NewSimpleMetadataClient(scheme,
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group2/version", "TheKind", "ns-foo", "name2-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-bar"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-baz"),
|
||||
newPartialObjectMetadata("group2/version", "TheKind", "ns-foo", "name2-baz"),
|
||||
)
|
||||
listFirst, err := client.Resource(schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"}).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
expected := []metav1.PartialObjectMetadata{
|
||||
*newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
*newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-bar"),
|
||||
*newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-baz"),
|
||||
}
|
||||
if !equality.Semantic.DeepEqual(listFirst.Items, expected) {
|
||||
t.Fatal(diff.ObjectGoPrintDiff(expected, listFirst.Items))
|
||||
}
|
||||
}
|
||||
|
||||
type patchTestCase struct {
|
||||
name string
|
||||
object runtime.Object
|
||||
patchType types.PatchType
|
||||
patchBytes []byte
|
||||
wantErrMsg string
|
||||
expectedPatchedObject runtime.Object
|
||||
}
|
||||
|
||||
func (tc *patchTestCase) runner(t *testing.T) {
|
||||
client := NewSimpleMetadataClient(scheme, tc.object)
|
||||
resourceInterface := client.Resource(schema.GroupVersionResource{Group: testGroup, Version: testVersion, Resource: testResource}).Namespace(testNamespace)
|
||||
|
||||
got, recErr := resourceInterface.Patch(testName, tc.patchType, tc.patchBytes, metav1.PatchOptions{})
|
||||
|
||||
if err := tc.verifyErr(recErr); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err := tc.verifyResult(got); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// verifyErr verifies that the given error returned from Patch is the error
|
||||
// expected by the test case.
|
||||
func (tc *patchTestCase) verifyErr(err error) error {
|
||||
if tc.wantErrMsg != "" && err == nil {
|
||||
return fmt.Errorf("want error, got nil")
|
||||
}
|
||||
|
||||
if tc.wantErrMsg == "" && err != nil {
|
||||
return fmt.Errorf("want no error, got %v", err)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if want, got := tc.wantErrMsg, err.Error(); want != got {
|
||||
return fmt.Errorf("incorrect error: want: %q got: %q", want, got)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tc *patchTestCase) verifyResult(result *metav1.PartialObjectMetadata) error {
|
||||
if tc.expectedPatchedObject == nil && result == nil {
|
||||
return nil
|
||||
}
|
||||
if !equality.Semantic.DeepEqual(result, tc.expectedPatchedObject) {
|
||||
return fmt.Errorf("unexpected diff in received object: %s", diff.ObjectGoPrintDiff(tc.expectedPatchedObject, result))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestPatch(t *testing.T) {
|
||||
testCases := []patchTestCase{
|
||||
{
|
||||
name: "jsonpatch fails with merge type",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
patchType: types.StrategicMergePatchType,
|
||||
patchBytes: []byte(`[]`),
|
||||
wantErrMsg: "invalid JSON document",
|
||||
}, {
|
||||
name: "jsonpatch works with empty patch",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
patchType: types.JSONPatchType,
|
||||
// No-op
|
||||
patchBytes: []byte(`[]`),
|
||||
expectedPatchedObject: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
}, {
|
||||
name: "jsonpatch works with simple change patch",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
patchType: types.JSONPatchType,
|
||||
// change spec.foo from bar to foobar
|
||||
patchBytes: []byte(`[{"op": "replace", "path": "/metadata/annotations/foo", "value": "foobar"}]`),
|
||||
expectedPatchedObject: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "foobar"}),
|
||||
}, {
|
||||
name: "jsonpatch works with simple addition",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
patchType: types.JSONPatchType,
|
||||
// add spec.newvalue = dummy
|
||||
patchBytes: []byte(`[{"op": "add", "path": "/metadata/annotations/newvalue", "value": "dummy"}]`),
|
||||
expectedPatchedObject: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar", "newvalue": "dummy"}),
|
||||
}, {
|
||||
name: "jsonpatch works with simple deletion",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar", "toremove": "shouldnotbehere"}),
|
||||
patchType: types.JSONPatchType,
|
||||
// remove spec.newvalue = dummy
|
||||
patchBytes: []byte(`[{"op": "remove", "path": "/metadata/annotations/toremove"}]`),
|
||||
expectedPatchedObject: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
}, {
|
||||
name: "strategic merge patch fails with JSONPatch",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
patchType: types.StrategicMergePatchType,
|
||||
// add spec.newvalue = dummy
|
||||
patchBytes: []byte(`[{"op": "add", "path": "/metadata/annotations/newvalue", "value": "dummy"}]`),
|
||||
wantErrMsg: "invalid JSON document",
|
||||
}, {
|
||||
name: "merge patch works with simple replacement",
|
||||
object: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "bar"}),
|
||||
patchType: types.MergePatchType,
|
||||
patchBytes: []byte(`{ "metadata": {"annotations": { "foo": "baz" } } }`),
|
||||
expectedPatchedObject: newPartialObjectMetadataWithAnnotations(map[string]string{"foo": "baz"}),
|
||||
},
|
||||
// TODO: Add tests for strategic merge using v1.Pod for example to ensure the test cases
|
||||
// demonstrate expected use cases.
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, tc.runner)
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes 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 metadata
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
// Interface allows a caller to get the metadata (in the form of PartialObjectMetadata objects)
|
||||
// from any Kubernetes compatible resource API.
|
||||
type Interface interface {
|
||||
Resource(resource schema.GroupVersionResource) Getter
|
||||
}
|
||||
|
||||
// ResourceInterface contains the set of methods that may be invoked on objects by their metadata.
|
||||
// Update is not supported by the server, but Patch can be used for the actions Update would handle.
|
||||
type ResourceInterface interface {
|
||||
Delete(name string, options *metav1.DeleteOptions, subresources ...string) error
|
||||
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
|
||||
Get(name string, options metav1.GetOptions, subresources ...string) (*metav1.PartialObjectMetadata, error)
|
||||
List(opts metav1.ListOptions) (*metav1.PartialObjectMetadataList, error)
|
||||
Watch(opts metav1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*metav1.PartialObjectMetadata, error)
|
||||
}
|
||||
|
||||
// Getter handles both namespaced and non-namespaced resource types consistently.
|
||||
type Getter interface {
|
||||
Namespace(string) ResourceInterface
|
||||
ResourceInterface
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
var deleteScheme = runtime.NewScheme()
|
||||
var parameterScheme = runtime.NewScheme()
|
||||
var deleteOptionsCodec = serializer.NewCodecFactory(deleteScheme)
|
||||
var dynamicParameterCodec = runtime.NewParameterCodec(parameterScheme)
|
||||
|
||||
var versionV1 = schema.GroupVersion{Version: "v1"}
|
||||
|
||||
func init() {
|
||||
metav1.AddToGroupVersion(parameterScheme, versionV1)
|
||||
metav1.AddToGroupVersion(deleteScheme, versionV1)
|
||||
}
|
||||
|
||||
// Client allows callers to retrieve the object metadata for any
|
||||
// Kubernetes-compatible API endpoint. The client uses the
|
||||
// meta.k8s.io/v1 PartialObjectMetadata resource to more efficiently
|
||||
// retrieve just the necessary metadata, but on older servers
|
||||
// (Kubernetes 1.14 and before) will retrieve the object and then
|
||||
// convert the metadata.
|
||||
type Client struct {
|
||||
client *rest.RESTClient
|
||||
}
|
||||
|
||||
var _ Interface = &Client{}
|
||||
|
||||
// ConfigFor returns a copy of the provided config with the
|
||||
// appropriate metadata client defaults set.
|
||||
func ConfigFor(inConfig *rest.Config) *rest.Config {
|
||||
config := rest.CopyConfig(inConfig)
|
||||
config.AcceptContentTypes = "application/vnd.kubernetes.protobuf,application/json"
|
||||
config.ContentType = "application/vnd.kubernetes.protobuf"
|
||||
config.NegotiatedSerializer = metainternalversion.Codecs.WithoutConversion()
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new metadata client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) Interface {
|
||||
ret, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// NewForConfig creates a new metadata client that can retrieve object
|
||||
// metadata details about any Kubernetes object (core, aggregated, or custom
|
||||
// resource based) in the form of PartialObjectMetadata objects, or returns
|
||||
// an error.
|
||||
func NewForConfig(inConfig *rest.Config) (Interface, error) {
|
||||
config := ConfigFor(inConfig)
|
||||
// for serializing the options
|
||||
config.GroupVersion = &schema.GroupVersion{}
|
||||
config.APIPath = "/this-value-should-never-be-sent"
|
||||
|
||||
restClient, err := rest.RESTClientFor(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Client{client: restClient}, nil
|
||||
}
|
||||
|
||||
type client struct {
|
||||
client *Client
|
||||
namespace string
|
||||
resource schema.GroupVersionResource
|
||||
}
|
||||
|
||||
// Resource returns an interface that can access cluster or namespace
|
||||
// scoped instances of resource.
|
||||
func (c *Client) Resource(resource schema.GroupVersionResource) Getter {
|
||||
return &client{client: c, resource: resource}
|
||||
}
|
||||
|
||||
// Namespace returns an interface that can access namespace-scoped instances of the
|
||||
// provided resource.
|
||||
func (c *client) Namespace(ns string) ResourceInterface {
|
||||
ret := *c
|
||||
ret.namespace = ns
|
||||
return &ret
|
||||
}
|
||||
|
||||
// Delete removes the provided resource from the server.
|
||||
func (c *client) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
|
||||
if len(name) == 0 {
|
||||
return fmt.Errorf("name is required")
|
||||
}
|
||||
if opts == nil {
|
||||
opts = &metav1.DeleteOptions{}
|
||||
}
|
||||
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := c.client.client.
|
||||
Delete().
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(deleteOptionsByte).
|
||||
Do()
|
||||
return result.Error()
|
||||
}
|
||||
|
||||
// DeleteCollection triggers deletion of all resources in the specified scope (namespace or cluster).
|
||||
func (c *client) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
if opts == nil {
|
||||
opts = &metav1.DeleteOptions{}
|
||||
}
|
||||
deleteOptionsByte, err := runtime.Encode(deleteOptionsCodec.LegacyCodec(schema.GroupVersion{Version: "v1"}), opts)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result := c.client.client.
|
||||
Delete().
|
||||
AbsPath(c.makeURLSegments("")...).
|
||||
Body(deleteOptionsByte).
|
||||
SpecificallyVersionedParams(&listOptions, dynamicParameterCodec, versionV1).
|
||||
Do()
|
||||
return result.Error()
|
||||
}
|
||||
|
||||
// Get returns the resource with name from the specified scope (namespace or cluster).
|
||||
func (c *client) Get(name string, opts metav1.GetOptions, subresources ...string) (*metav1.PartialObjectMetadata, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
SetHeader("Accept", "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json").
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do()
|
||||
if err := result.Error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj, err := result.Get()
|
||||
if runtime.IsNotRegisteredError(err) {
|
||||
klog.V(5).Infof("Unable to retrieve PartialObjectMetadata: %#v", err)
|
||||
rawBytes, err := result.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var partial metav1.PartialObjectMetadata
|
||||
if err := json.Unmarshal(rawBytes, &partial); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode returned object as PartialObjectMetadata: %v", err)
|
||||
}
|
||||
if !isLikelyObjectMetadata(&partial) {
|
||||
return nil, fmt.Errorf("object does not appear to match the ObjectMeta schema: %#v", partial)
|
||||
}
|
||||
partial.TypeMeta = metav1.TypeMeta{}
|
||||
return &partial, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
partial, ok := obj.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected object, expected PartialObjectMetadata but got %T", obj)
|
||||
}
|
||||
return partial, nil
|
||||
}
|
||||
|
||||
// List returns all resources within the specified scope (namespace or cluster).
|
||||
func (c *client) List(opts metav1.ListOptions) (*metav1.PartialObjectMetadataList, error) {
|
||||
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).
|
||||
SetHeader("Accept", "application/vnd.kubernetes.protobuf;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1,application/json").
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do()
|
||||
if err := result.Error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj, err := result.Get()
|
||||
if runtime.IsNotRegisteredError(err) {
|
||||
klog.V(5).Infof("Unable to retrieve PartialObjectMetadataList: %#v", err)
|
||||
rawBytes, err := result.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var partial metav1.PartialObjectMetadataList
|
||||
if err := json.Unmarshal(rawBytes, &partial); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode returned object as PartialObjectMetadataList: %v", err)
|
||||
}
|
||||
partial.TypeMeta = metav1.TypeMeta{}
|
||||
return &partial, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
partial, ok := obj.(*metav1.PartialObjectMetadataList)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected object, expected PartialObjectMetadata but got %T", obj)
|
||||
}
|
||||
return partial, nil
|
||||
}
|
||||
|
||||
// Watch finds all changes to the resources in the specified scope (namespace or cluster).
|
||||
func (c *client) Watch(opts metav1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.client.Get().
|
||||
AbsPath(c.makeURLSegments("")...).
|
||||
SetHeader("Accept", "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json").
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Timeout(timeout).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Patch modifies the named resource in the specified scope (namespace or cluster).
|
||||
func (c *client) Patch(name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (*metav1.PartialObjectMetadata, error) {
|
||||
if len(name) == 0 {
|
||||
return nil, fmt.Errorf("name is required")
|
||||
}
|
||||
result := c.client.client.
|
||||
Patch(pt).
|
||||
AbsPath(append(c.makeURLSegments(name), subresources...)...).
|
||||
Body(data).
|
||||
SetHeader("Accept", "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json").
|
||||
SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).
|
||||
Do()
|
||||
if err := result.Error(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
obj, err := result.Get()
|
||||
if runtime.IsNotRegisteredError(err) {
|
||||
rawBytes, err := result.Raw()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var partial metav1.PartialObjectMetadata
|
||||
if err := json.Unmarshal(rawBytes, &partial); err != nil {
|
||||
return nil, fmt.Errorf("unable to decode returned object as PartialObjectMetadata: %v", err)
|
||||
}
|
||||
if !isLikelyObjectMetadata(&partial) {
|
||||
return nil, fmt.Errorf("object does not appear to match the ObjectMeta schema")
|
||||
}
|
||||
partial.TypeMeta = metav1.TypeMeta{}
|
||||
return &partial, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
partial, ok := obj.(*metav1.PartialObjectMetadata)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected object, expected PartialObjectMetadata but got %T", obj)
|
||||
}
|
||||
return partial, nil
|
||||
}
|
||||
|
||||
func (c *client) makeURLSegments(name string) []string {
|
||||
url := []string{}
|
||||
if len(c.resource.Group) == 0 {
|
||||
url = append(url, "api")
|
||||
} else {
|
||||
url = append(url, "apis", c.resource.Group)
|
||||
}
|
||||
url = append(url, c.resource.Version)
|
||||
|
||||
if len(c.namespace) > 0 {
|
||||
url = append(url, "namespaces", c.namespace)
|
||||
}
|
||||
url = append(url, c.resource.Resource)
|
||||
|
||||
if len(name) > 0 {
|
||||
url = append(url, name)
|
||||
}
|
||||
|
||||
return url
|
||||
}
|
||||
|
||||
func isLikelyObjectMetadata(meta *metav1.PartialObjectMetadata) bool {
|
||||
return len(meta.UID) > 0 || !meta.CreationTimestamp.IsZero() || len(meta.Name) > 0 || len(meta.GenerateName) > 0
|
||||
}
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes 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 metadata
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
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/diff"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
gvr := schema.GroupVersionResource{Group: "group", Version: "v1", Resource: "resource"}
|
||||
|
||||
writeJSON := func(t *testing.T, w http.ResponseWriter, obj runtime.Object) {
|
||||
data, err := json.Marshal(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if _, err := w.Write(data); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
handler func(t *testing.T, w http.ResponseWriter, req *http.Request)
|
||||
want func(t *testing.T, client *Client)
|
||||
}{
|
||||
{
|
||||
name: "GET is able to convert a JSON object to PartialObjectMetadata",
|
||||
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
|
||||
t.Fatal(req.Header.Get("Accept"))
|
||||
}
|
||||
if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
|
||||
t.Fatal(req.URL.String())
|
||||
}
|
||||
writeJSON(t, w, &corev1.Pod{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
},
|
||||
})
|
||||
},
|
||||
want: func(t *testing.T, client *Client) {
|
||||
obj, err := client.Resource(gvr).Namespace("ns").Get("name", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expect := &metav1.PartialObjectMetadata{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(expect, obj) {
|
||||
t.Fatal(diff.ObjectReflectDiff(expect, obj))
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "LIST is able to convert a JSON object to PartialObjectMetadata",
|
||||
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadataList;g=meta.k8s.io;v=v1,application/json" {
|
||||
t.Fatal(req.Header.Get("Accept"))
|
||||
}
|
||||
if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource" {
|
||||
t.Fatal(req.URL.String())
|
||||
}
|
||||
writeJSON(t, w, &corev1.PodList{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "PodList",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ListMeta: metav1.ListMeta{
|
||||
ResourceVersion: "253",
|
||||
},
|
||||
Items: []corev1.Pod{
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
want: func(t *testing.T, client *Client) {
|
||||
objs, err := client.Resource(gvr).Namespace("ns").List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if objs.GetResourceVersion() != "253" {
|
||||
t.Fatal(objs)
|
||||
}
|
||||
expect := []metav1.PartialObjectMetadata{
|
||||
{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "ns",
|
||||
},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(expect, objs.Items) {
|
||||
t.Fatal(diff.ObjectReflectDiff(expect, objs.Items))
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "GET fails if the object is JSON and has no kind",
|
||||
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
|
||||
t.Fatal(req.Header.Get("Accept"))
|
||||
}
|
||||
if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
|
||||
t.Fatal(req.URL.String())
|
||||
}
|
||||
writeJSON(t, w, &corev1.Pod{
|
||||
TypeMeta: metav1.TypeMeta{},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "123",
|
||||
},
|
||||
})
|
||||
},
|
||||
want: func(t *testing.T, client *Client) {
|
||||
obj, err := client.Resource(gvr).Namespace("ns").Get("name", metav1.GetOptions{})
|
||||
if err == nil || !runtime.IsMissingKind(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if obj != nil {
|
||||
t.Fatal(obj)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "GET fails if the object is JSON and has no apiVersion",
|
||||
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
|
||||
t.Fatal(req.Header.Get("Accept"))
|
||||
}
|
||||
if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
|
||||
t.Fatal(req.URL.String())
|
||||
}
|
||||
writeJSON(t, w, &corev1.Pod{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "123",
|
||||
},
|
||||
})
|
||||
},
|
||||
want: func(t *testing.T, client *Client) {
|
||||
obj, err := client.Resource(gvr).Namespace("ns").Get("name", metav1.GetOptions{})
|
||||
if err == nil || !runtime.IsMissingVersion(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if obj != nil {
|
||||
t.Fatal(obj)
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "GET fails if the object is JSON and not clearly metadata",
|
||||
handler: func(t *testing.T, w http.ResponseWriter, req *http.Request) {
|
||||
if req.Header.Get("Accept") != "application/vnd.kubernetes.protobuf;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json;as=PartialObjectMetadata;g=meta.k8s.io;v=v1,application/json" {
|
||||
t.Fatal(req.Header.Get("Accept"))
|
||||
}
|
||||
if req.Method != "GET" && req.URL.String() != "/apis/group/v1/namespaces/ns/resource/name" {
|
||||
t.Fatal(req.URL.String())
|
||||
}
|
||||
writeJSON(t, w, &corev1.Pod{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{},
|
||||
})
|
||||
},
|
||||
want: func(t *testing.T, client *Client) {
|
||||
obj, err := client.Resource(gvr).Namespace("ns").Get("name", metav1.GetOptions{})
|
||||
if err == nil || !strings.Contains(err.Error(), "object does not appear to match the ObjectMeta schema") {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if obj != nil {
|
||||
t.Fatal(obj)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range testCases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { tt.handler(t, w, req) }))
|
||||
defer s.Close()
|
||||
|
||||
cfg := ConfigFor(&rest.Config{Host: s.URL})
|
||||
client := NewForConfigOrDie(cfg).(*Client)
|
||||
tt.want(t, client)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatainformer
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/metadata"
|
||||
"k8s.io/client-go/metadata/metadatalister"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of metadataSharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client metadata.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewFilteredSharedInformerFactory(client, defaultResync, metav1.NamespaceAll, nil)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of metadataSharedInformerFactory.
|
||||
// Listers obtained via this factory will be subject to the same filters as specified here.
|
||||
func NewFilteredSharedInformerFactory(client metadata.Interface, defaultResync time.Duration, namespace string, tweakListOptions TweakListOptionsFunc) SharedInformerFactory {
|
||||
return &metadataSharedInformerFactory{
|
||||
client: client,
|
||||
defaultResync: defaultResync,
|
||||
namespace: namespace,
|
||||
informers: map[schema.GroupVersionResource]informers.GenericInformer{},
|
||||
startedInformers: make(map[schema.GroupVersionResource]bool),
|
||||
tweakListOptions: tweakListOptions,
|
||||
}
|
||||
}
|
||||
|
||||
type metadataSharedInformerFactory struct {
|
||||
client metadata.Interface
|
||||
defaultResync time.Duration
|
||||
namespace string
|
||||
|
||||
lock sync.Mutex
|
||||
informers map[schema.GroupVersionResource]informers.GenericInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[schema.GroupVersionResource]bool
|
||||
tweakListOptions TweakListOptionsFunc
|
||||
}
|
||||
|
||||
var _ SharedInformerFactory = &metadataSharedInformerFactory{}
|
||||
|
||||
func (f *metadataSharedInformerFactory) ForResource(gvr schema.GroupVersionResource) informers.GenericInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
key := gvr
|
||||
informer, exists := f.informers[key]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
informer = NewFilteredMetadataInformer(f.client, gvr, f.namespace, f.defaultResync, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
f.informers[key] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *metadataSharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Informer().Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *metadataSharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool {
|
||||
informers := func() map[schema.GroupVersionResource]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[schema.GroupVersionResource]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer.Informer()
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[schema.GroupVersionResource]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// NewFilteredMetadataInformer constructs a new informer for a metadata type.
|
||||
func NewFilteredMetadataInformer(client metadata.Interface, gvr schema.GroupVersionResource, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions TweakListOptionsFunc) informers.GenericInformer {
|
||||
return &metadataInformer{
|
||||
gvr: gvr,
|
||||
informer: cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Resource(gvr).Namespace(namespace).List(options)
|
||||
},
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Resource(gvr).Namespace(namespace).Watch(options)
|
||||
},
|
||||
},
|
||||
&metav1.PartialObjectMetadata{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
type metadataInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
var _ informers.GenericInformer = &metadataInformer{}
|
||||
|
||||
func (d *metadataInformer) Informer() cache.SharedIndexInformer {
|
||||
return d.informer
|
||||
}
|
||||
|
||||
func (d *metadataInformer) Lister() cache.GenericLister {
|
||||
return metadatalister.NewRuntimeObjectShim(metadatalister.New(d.informer.GetIndexer(), d.gvr))
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatainformer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/client-go/metadata/fake"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
func init() {
|
||||
klog.InitFlags(flag.CommandLine)
|
||||
flag.CommandLine.Lookup("v").Value.Set("5")
|
||||
flag.CommandLine.Lookup("alsologtostderr").Value.Set("true")
|
||||
}
|
||||
|
||||
func TestMetadataSharedInformerFactory(t *testing.T) {
|
||||
scenarios := []struct {
|
||||
name string
|
||||
existingObj *metav1.PartialObjectMetadata
|
||||
gvr schema.GroupVersionResource
|
||||
ns string
|
||||
trigger func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeMetadataClient, testObject *metav1.PartialObjectMetadata) *metav1.PartialObjectMetadata
|
||||
handler func(rcvCh chan<- *metav1.PartialObjectMetadata) *cache.ResourceEventHandlerFuncs
|
||||
}{
|
||||
// scenario 1
|
||||
{
|
||||
name: "scenario 1: test if adding an object triggers AddFunc",
|
||||
ns: "ns-foo",
|
||||
gvr: schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"},
|
||||
trigger: func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeMetadataClient, _ *metav1.PartialObjectMetadata) *metav1.PartialObjectMetadata {
|
||||
testObject := newPartialObjectMetadata("extensions/v1beta1", "Deployment", "ns-foo", "name-foo")
|
||||
createdObj, err := fakeClient.Resource(gvr).Namespace(ns).(fake.MetadataClient).CreateFake(testObject, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return createdObj
|
||||
},
|
||||
handler: func(rcvCh chan<- *metav1.PartialObjectMetadata) *cache.ResourceEventHandlerFuncs {
|
||||
return &cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
rcvCh <- obj.(*metav1.PartialObjectMetadata)
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// scenario 2
|
||||
{
|
||||
name: "scenario 2: tests if updating an object triggers UpdateFunc",
|
||||
ns: "ns-foo",
|
||||
gvr: schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"},
|
||||
existingObj: newPartialObjectMetadata("extensions/v1beta1", "Deployment", "ns-foo", "name-foo"),
|
||||
trigger: func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeMetadataClient, testObject *metav1.PartialObjectMetadata) *metav1.PartialObjectMetadata {
|
||||
if testObject.Annotations == nil {
|
||||
testObject.Annotations = make(map[string]string)
|
||||
}
|
||||
testObject.Annotations["test"] = "updatedName"
|
||||
updatedObj, err := fakeClient.Resource(gvr).Namespace(ns).(fake.MetadataClient).UpdateFake(testObject, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return updatedObj
|
||||
},
|
||||
handler: func(rcvCh chan<- *metav1.PartialObjectMetadata) *cache.ResourceEventHandlerFuncs {
|
||||
return &cache.ResourceEventHandlerFuncs{
|
||||
UpdateFunc: func(old, updated interface{}) {
|
||||
rcvCh <- updated.(*metav1.PartialObjectMetadata)
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
// scenario 3
|
||||
{
|
||||
name: "scenario 3: test if deleting an object triggers DeleteFunc",
|
||||
ns: "ns-foo",
|
||||
gvr: schema.GroupVersionResource{Group: "extensions", Version: "v1beta1", Resource: "deployments"},
|
||||
existingObj: newPartialObjectMetadata("extensions/v1beta1", "Deployment", "ns-foo", "name-foo"),
|
||||
trigger: func(gvr schema.GroupVersionResource, ns string, fakeClient *fake.FakeMetadataClient, testObject *metav1.PartialObjectMetadata) *metav1.PartialObjectMetadata {
|
||||
err := fakeClient.Resource(gvr).Namespace(ns).Delete(testObject.GetName(), &metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
return testObject
|
||||
},
|
||||
handler: func(rcvCh chan<- *metav1.PartialObjectMetadata) *cache.ResourceEventHandlerFuncs {
|
||||
return &cache.ResourceEventHandlerFuncs{
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
rcvCh <- obj.(*metav1.PartialObjectMetadata)
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, ts := range scenarios {
|
||||
t.Run(ts.name, func(t *testing.T) {
|
||||
// test data
|
||||
timeout := time.Duration(3 * time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
scheme := runtime.NewScheme()
|
||||
metav1.AddMetaToScheme(scheme)
|
||||
informerReciveObjectCh := make(chan *metav1.PartialObjectMetadata, 1)
|
||||
objs := []runtime.Object{}
|
||||
if ts.existingObj != nil {
|
||||
objs = append(objs, ts.existingObj)
|
||||
}
|
||||
fakeClient := fake.NewSimpleMetadataClient(scheme, objs...)
|
||||
target := NewSharedInformerFactory(fakeClient, 0)
|
||||
|
||||
// act
|
||||
informerListerForGvr := target.ForResource(ts.gvr)
|
||||
informerListerForGvr.Informer().AddEventHandler(ts.handler(informerReciveObjectCh))
|
||||
target.Start(ctx.Done())
|
||||
if synced := target.WaitForCacheSync(ctx.Done()); !synced[ts.gvr] {
|
||||
t.Fatalf("informer for %s hasn't synced", ts.gvr)
|
||||
}
|
||||
|
||||
testObject := ts.trigger(ts.gvr, ts.ns, fakeClient, ts.existingObj)
|
||||
select {
|
||||
case objFromInformer := <-informerReciveObjectCh:
|
||||
if !equality.Semantic.DeepEqual(testObject, objFromInformer) {
|
||||
t.Fatalf("%v", diff.ObjectDiff(testObject, objFromInformer))
|
||||
}
|
||||
case <-ctx.Done():
|
||||
t.Errorf("tested informer haven't received an object, waited %v", timeout)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newPartialObjectMetadata(apiVersion, kind, namespace, name string) *metav1.PartialObjectMetadata {
|
||||
return &metav1.PartialObjectMetadata{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: apiVersion,
|
||||
Kind: kind,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatainformer
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/informers"
|
||||
)
|
||||
|
||||
// SharedInformerFactory provides access to a shared informer and lister for dynamic client
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
ForResource(gvr schema.GroupVersionResource) informers.GenericInformer
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[schema.GroupVersionResource]bool
|
||||
}
|
||||
|
||||
// TweakListOptionsFunc defines the signature of a helper function
|
||||
// that wants to provide more listing options to API
|
||||
type TweakListOptionsFunc func(*metav1.ListOptions)
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatalister
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
)
|
||||
|
||||
// Lister helps list resources.
|
||||
type Lister interface {
|
||||
// List lists all resources in the indexer.
|
||||
List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error)
|
||||
// Get retrieves a resource from the indexer with the given name
|
||||
Get(name string) (*metav1.PartialObjectMetadata, error)
|
||||
// Namespace returns an object that can list and get resources in a given namespace.
|
||||
Namespace(namespace string) NamespaceLister
|
||||
}
|
||||
|
||||
// NamespaceLister helps list and get resources.
|
||||
type NamespaceLister interface {
|
||||
// List lists all resources in the indexer for a given namespace.
|
||||
List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error)
|
||||
// Get retrieves a resource from the indexer for a given namespace and name.
|
||||
Get(name string) (*metav1.PartialObjectMetadata, error)
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatalister
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
var _ Lister = &metadataLister{}
|
||||
var _ NamespaceLister = &metadataNamespaceLister{}
|
||||
|
||||
// metadataLister implements the Lister interface.
|
||||
type metadataLister struct {
|
||||
indexer cache.Indexer
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
// New returns a new Lister.
|
||||
func New(indexer cache.Indexer, gvr schema.GroupVersionResource) Lister {
|
||||
return &metadataLister{indexer: indexer, gvr: gvr}
|
||||
}
|
||||
|
||||
// List lists all resources in the indexer.
|
||||
func (l *metadataLister) List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error) {
|
||||
err = cache.ListAll(l.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*metav1.PartialObjectMetadata))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves a resource from the indexer with the given name
|
||||
func (l *metadataLister) Get(name string) (*metav1.PartialObjectMetadata, error) {
|
||||
obj, exists, err := l.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(l.gvr.GroupResource(), name)
|
||||
}
|
||||
return obj.(*metav1.PartialObjectMetadata), nil
|
||||
}
|
||||
|
||||
// Namespace returns an object that can list and get resources from a given namespace.
|
||||
func (l *metadataLister) Namespace(namespace string) NamespaceLister {
|
||||
return &metadataNamespaceLister{indexer: l.indexer, namespace: namespace, gvr: l.gvr}
|
||||
}
|
||||
|
||||
// metadataNamespaceLister implements the NamespaceLister interface.
|
||||
type metadataNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
gvr schema.GroupVersionResource
|
||||
}
|
||||
|
||||
// List lists all resources in the indexer for a given namespace.
|
||||
func (l *metadataNamespaceLister) List(selector labels.Selector) (ret []*metav1.PartialObjectMetadata, err error) {
|
||||
err = cache.ListAllByNamespace(l.indexer, l.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*metav1.PartialObjectMetadata))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves a resource from the indexer for a given namespace and name.
|
||||
func (l *metadataNamespaceLister) Get(name string) (*metav1.PartialObjectMetadata, error) {
|
||||
obj, exists, err := l.indexer.GetByKey(l.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(l.gvr.GroupResource(), name)
|
||||
}
|
||||
return obj.(*metav1.PartialObjectMetadata), nil
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatalister
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
func TestNamespaceGetMethod(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
existingObjects []runtime.Object
|
||||
namespaceToSync string
|
||||
gvrToSync schema.GroupVersionResource
|
||||
objectToGet string
|
||||
expectedObject *metav1.PartialObjectMetadata
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "scenario 1: gets name-foo1 resource from the indexer from ns-foo namespace",
|
||||
existingObjects: []runtime.Object{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo1"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-bar", "name-bar"),
|
||||
},
|
||||
namespaceToSync: "ns-foo",
|
||||
gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"},
|
||||
objectToGet: "name-foo1",
|
||||
expectedObject: newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo1"),
|
||||
},
|
||||
{
|
||||
name: "scenario 2: gets name-foo-non-existing resource from the indexer from ns-foo namespace",
|
||||
existingObjects: []runtime.Object{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo1"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-bar", "name-bar"),
|
||||
},
|
||||
namespaceToSync: "ns-foo",
|
||||
gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"},
|
||||
objectToGet: "name-foo-non-existing",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// test data
|
||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
for _, obj := range test.existingObjects {
|
||||
err := indexer.Add(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// act
|
||||
target := New(indexer, test.gvrToSync).Namespace(test.namespaceToSync)
|
||||
actualObject, err := target.Get(test.objectToGet)
|
||||
|
||||
// validate
|
||||
if test.expectError {
|
||||
if err == nil {
|
||||
t.Fatal("expected to get an error but non was returned")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(test.expectedObject, actualObject) {
|
||||
t.Fatalf("unexpected object has been returned expected = %v actual = %v, diff = %v", test.expectedObject, actualObject, diff.ObjectDiff(test.expectedObject, actualObject))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNamespaceListMethod(t *testing.T) {
|
||||
// test data
|
||||
objs := []runtime.Object{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo1"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-bar", "name-bar"),
|
||||
}
|
||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
for _, obj := range objs {
|
||||
err := indexer.Add(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
expectedOutput := []*metav1.PartialObjectMetadata{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo1"),
|
||||
}
|
||||
namespaceToList := "ns-foo"
|
||||
|
||||
// act
|
||||
target := New(indexer, schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"}).Namespace(namespaceToList)
|
||||
actualOutput, err := target.List(labels.Everything())
|
||||
|
||||
// validate
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertListOrDie(expectedOutput, actualOutput, t)
|
||||
}
|
||||
|
||||
func TestListerGetMethod(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
existingObjects []runtime.Object
|
||||
namespaceToSync string
|
||||
gvrToSync schema.GroupVersionResource
|
||||
objectToGet string
|
||||
expectedObject *metav1.PartialObjectMetadata
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "scenario 1: gets name-foo1 resource from the indexer",
|
||||
existingObjects: []runtime.Object{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "", "name-foo1"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-bar", "name-bar"),
|
||||
},
|
||||
namespaceToSync: "",
|
||||
gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"},
|
||||
objectToGet: "name-foo1",
|
||||
expectedObject: newPartialObjectMetadata("group/version", "TheKind", "", "name-foo1"),
|
||||
},
|
||||
{
|
||||
name: "scenario 2: doesn't get name-foo resource from the indexer from ns-foo namespace",
|
||||
existingObjects: []runtime.Object{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo1"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-bar", "name-bar"),
|
||||
},
|
||||
namespaceToSync: "ns-foo",
|
||||
gvrToSync: schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"},
|
||||
objectToGet: "name-foo",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// test data
|
||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
for _, obj := range test.existingObjects {
|
||||
err := indexer.Add(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
// act
|
||||
target := New(indexer, test.gvrToSync)
|
||||
actualObject, err := target.Get(test.objectToGet)
|
||||
|
||||
// validate
|
||||
if test.expectError {
|
||||
if err == nil {
|
||||
t.Fatal("expected to get an error but non was returned")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(test.expectedObject, actualObject) {
|
||||
t.Fatalf("unexpected object has been returned expected = %v actual = %v, diff = %v", test.expectedObject, actualObject, diff.ObjectDiff(test.expectedObject, actualObject))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListerListMethod(t *testing.T) {
|
||||
// test data
|
||||
objs := []runtime.Object{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-bar"),
|
||||
}
|
||||
indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{})
|
||||
for _, obj := range objs {
|
||||
err := indexer.Add(obj)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
expectedOutput := []*metav1.PartialObjectMetadata{
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-foo"),
|
||||
newPartialObjectMetadata("group/version", "TheKind", "ns-foo", "name-bar"),
|
||||
}
|
||||
|
||||
// act
|
||||
target := New(indexer, schema.GroupVersionResource{Group: "group", Version: "version", Resource: "TheKinds"})
|
||||
actualOutput, err := target.List(labels.Everything())
|
||||
|
||||
// validate
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
assertListOrDie(expectedOutput, actualOutput, t)
|
||||
}
|
||||
|
||||
func assertListOrDie(expected, actual []*metav1.PartialObjectMetadata, t *testing.T) {
|
||||
if len(actual) != len(expected) {
|
||||
t.Fatalf("unexpected number of items returned, expected = %d, actual = %d", len(expected), len(actual))
|
||||
}
|
||||
for _, expectedObject := range expected {
|
||||
found := false
|
||||
for _, actualObject := range actual {
|
||||
if actualObject.GetName() == expectedObject.GetName() {
|
||||
if !reflect.DeepEqual(expectedObject, actualObject) {
|
||||
t.Fatalf("unexpected object has been returned expected = %v actual = %v, diff = %v", expectedObject, actualObject, diff.ObjectDiff(expectedObject, actualObject))
|
||||
}
|
||||
found = true
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatalf("the resource with the name = %s was not found in the returned output", expectedObject.GetName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newPartialObjectMetadata(apiVersion, kind, namespace, name string) *metav1.PartialObjectMetadata {
|
||||
return &metav1.PartialObjectMetadata{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: apiVersion,
|
||||
Kind: kind,
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 metadatalister
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
var _ cache.GenericLister = &metadataListerShim{}
|
||||
var _ cache.GenericNamespaceLister = &metadataNamespaceListerShim{}
|
||||
|
||||
// metadataListerShim implements the cache.GenericLister interface.
|
||||
type metadataListerShim struct {
|
||||
lister Lister
|
||||
}
|
||||
|
||||
// NewRuntimeObjectShim returns a new shim for Lister.
|
||||
// It wraps Lister so that it implements cache.GenericLister interface
|
||||
func NewRuntimeObjectShim(lister Lister) cache.GenericLister {
|
||||
return &metadataListerShim{lister: lister}
|
||||
}
|
||||
|
||||
// List will return all objects across namespaces
|
||||
func (s *metadataListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) {
|
||||
objs, err := s.lister.List(selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret = make([]runtime.Object, len(objs))
|
||||
for index, obj := range objs {
|
||||
ret[index] = obj
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get will attempt to retrieve assuming that name==key
|
||||
func (s *metadataListerShim) Get(name string) (runtime.Object, error) {
|
||||
return s.lister.Get(name)
|
||||
}
|
||||
|
||||
func (s *metadataListerShim) ByNamespace(namespace string) cache.GenericNamespaceLister {
|
||||
return &metadataNamespaceListerShim{
|
||||
namespaceLister: s.lister.Namespace(namespace),
|
||||
}
|
||||
}
|
||||
|
||||
// metadataNamespaceListerShim implements the NamespaceLister interface.
|
||||
// It wraps NamespaceLister so that it implements cache.GenericNamespaceLister interface
|
||||
type metadataNamespaceListerShim struct {
|
||||
namespaceLister NamespaceLister
|
||||
}
|
||||
|
||||
// List will return all objects in this namespace
|
||||
func (ns *metadataNamespaceListerShim) List(selector labels.Selector) (ret []runtime.Object, err error) {
|
||||
objs, err := ns.namespaceLister.List(selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret = make([]runtime.Object, len(objs))
|
||||
for index, obj := range objs {
|
||||
ret[index] = obj
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get will attempt to retrieve by namespace and name
|
||||
func (ns *metadataNamespaceListerShim) Get(name string) (runtime.Object, error) {
|
||||
return ns.namespaceLister.Get(name)
|
||||
}
|
||||
@@ -172,10 +172,6 @@ func (t *fakeLimiter) QPS() float32 {
|
||||
return t.FakeQPS
|
||||
}
|
||||
|
||||
func (t *fakeLimiter) Wait(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *fakeLimiter) Stop() {}
|
||||
|
||||
func (t *fakeLimiter) Accept() {}
|
||||
|
||||
@@ -55,7 +55,7 @@ func RegisterAuthProviderPlugin(name string, plugin Factory) error {
|
||||
pluginsLock.Lock()
|
||||
defer pluginsLock.Unlock()
|
||||
if _, found := plugins[name]; found {
|
||||
return fmt.Errorf("auth Provider Plugin %q was registered twice", name)
|
||||
return fmt.Errorf("Auth Provider Plugin %q was registered twice", name)
|
||||
}
|
||||
klog.V(4).Infof("Registered Auth Provider Plugin %q", name)
|
||||
plugins[name] = plugin
|
||||
@@ -67,7 +67,7 @@ func GetAuthProvider(clusterAddress string, apc *clientcmdapi.AuthProviderConfig
|
||||
defer pluginsLock.Unlock()
|
||||
p, ok := plugins[apc.Name]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no Auth Provider found for name %q", apc.Name)
|
||||
return nil, fmt.Errorf("No Auth Provider found for name %q", apc.Name)
|
||||
}
|
||||
return p(clusterAddress, apc.Config, persister)
|
||||
}
|
||||
|
||||
@@ -521,24 +521,14 @@ func (r Request) finalURLTemplate() url.URL {
|
||||
return *url
|
||||
}
|
||||
|
||||
func (r *Request) tryThrottle() error {
|
||||
if r.throttle == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Request) tryThrottle() {
|
||||
now := time.Now()
|
||||
var err error
|
||||
if r.ctx != nil {
|
||||
err = r.throttle.Wait(r.ctx)
|
||||
} else {
|
||||
if r.throttle != nil {
|
||||
r.throttle.Accept()
|
||||
}
|
||||
|
||||
if latency := time.Since(now); latency > longThrottleLatency {
|
||||
klog.V(4).Infof("Throttling request took %v, request: %s:%s", latency, r.verb, r.URL().String())
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Watch attempts to begin watching the requested location.
|
||||
@@ -640,18 +630,13 @@ func (r *Request) Stream() (io.ReadCloser, error) {
|
||||
return nil, r.err
|
||||
}
|
||||
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.tryThrottle()
|
||||
|
||||
url := r.URL().String()
|
||||
req, err := http.NewRequest(r.verb, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if r.body != nil {
|
||||
req.Body = ioutil.NopCloser(r.body)
|
||||
}
|
||||
if r.ctx != nil {
|
||||
req = req.WithContext(r.ctx)
|
||||
}
|
||||
@@ -747,9 +732,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
// We are retrying the request that we already send to apiserver
|
||||
// at least once before.
|
||||
// This request should also be throttled with the client-internal throttler.
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
return err
|
||||
}
|
||||
r.tryThrottle()
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
updateURLMetrics(r, resp, err)
|
||||
@@ -820,9 +803,7 @@ func (r *Request) request(fn func(*http.Request, *http.Response)) error {
|
||||
// * If the server responds with a status: *errors.StatusError or *errors.UnexpectedObjectError
|
||||
// * http.Client.Do errors are returned directly.
|
||||
func (r *Request) Do() Result {
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
return Result{err: err}
|
||||
}
|
||||
r.tryThrottle()
|
||||
|
||||
var result Result
|
||||
err := r.request(func(req *http.Request, resp *http.Response) {
|
||||
@@ -836,9 +817,7 @@ func (r *Request) Do() Result {
|
||||
|
||||
// DoRaw executes the request but does not process the response body.
|
||||
func (r *Request) DoRaw() ([]byte, error) {
|
||||
if err := r.tryThrottle(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.tryThrottle()
|
||||
|
||||
var result Result
|
||||
err := r.request(func(req *http.Request, resp *http.Response) {
|
||||
@@ -871,13 +850,13 @@ func (r *Request) transformResponse(resp *http.Response, req *http.Request) Resu
|
||||
// 3. Apiserver closes connection.
|
||||
// 4. client-go should catch this and return an error.
|
||||
klog.V(2).Infof("Stream error %#v when reading response body, may be caused by closed connection.", err)
|
||||
streamErr := fmt.Errorf("stream error when reading response body, may be caused by closed connection. Please retry. Original error: %v", err)
|
||||
streamErr := fmt.Errorf("Stream error when reading response body, may be caused by closed connection. Please retry. Original error: %v", err)
|
||||
return Result{
|
||||
err: streamErr,
|
||||
}
|
||||
default:
|
||||
klog.Errorf("Unexpected error when reading response body: %v", err)
|
||||
unexpectedErr := fmt.Errorf("unexpected error when reading response body. Please retry. Original error: %v", err)
|
||||
unexpectedErr := fmt.Errorf("Unexpected error when reading response body. Please retry. Original error: %v", err)
|
||||
return Result{
|
||||
err: unexpectedErr,
|
||||
}
|
||||
|
||||
19
rest/request_test.go
Normal file → Executable file
19
rest/request_test.go
Normal file → Executable file
@@ -1440,20 +1440,15 @@ func BenchmarkCheckRetryClosesBody(b *testing.B) {
|
||||
defer testServer.Close()
|
||||
|
||||
c := testRESTClient(b, testServer)
|
||||
r := c.Verb("POST").
|
||||
Prefix("foo", "bar").
|
||||
Suffix("baz").
|
||||
Timeout(time.Second).
|
||||
Body([]byte(strings.Repeat("abcd", 1000)))
|
||||
|
||||
requests := make([]*Request, 0, b.N)
|
||||
for i := 0; i < b.N; i++ {
|
||||
requests = append(requests, c.Verb("POST").
|
||||
Prefix("foo", "bar").
|
||||
Suffix("baz").
|
||||
Timeout(time.Second).
|
||||
Body([]byte(strings.Repeat("abcd", 1000))))
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if _, err := requests[i].DoRaw(); err != nil {
|
||||
b.Fatalf("Unexpected error (%d/%d): %v", i, b.N, err)
|
||||
if _, err := r.DoRaw(); err != nil {
|
||||
b.Fatalf("Unexpected error: %v %#v", err, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,4 +18,4 @@ limitations under the License.
|
||||
// and updating Scale for any resource which implements the `scale` subresource,
|
||||
// as long as that subresource operates on a version of scale convertable to
|
||||
// autoscaling.Scale.
|
||||
package scale // import "k8s.io/client-go/scale"
|
||||
package scale
|
||||
|
||||
@@ -18,11 +18,9 @@ package testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -141,11 +139,6 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc {
|
||||
return true, nil, err
|
||||
}
|
||||
|
||||
// reset the object in preparation to unmarshal, since unmarshal does not guarantee that fields
|
||||
// in obj that are removed by patch are cleared
|
||||
value := reflect.ValueOf(obj)
|
||||
value.Elem().Set(reflect.New(value.Type().Elem()).Elem())
|
||||
|
||||
switch action.GetPatchType() {
|
||||
case types.JSONPatchType:
|
||||
patch, err := jsonpatch.DecodePatch(action.GetPatch())
|
||||
@@ -156,7 +149,6 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc {
|
||||
if err != nil {
|
||||
return true, nil, err
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(modified, obj); err != nil {
|
||||
return true, nil, err
|
||||
}
|
||||
@@ -318,11 +310,6 @@ func (t *tracker) Add(obj runtime.Object) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if partial, ok := obj.(*metav1.PartialObjectMetadata); ok && len(partial.TypeMeta.APIVersion) > 0 {
|
||||
gvks = []schema.GroupVersionKind{partial.TypeMeta.GroupVersionKind()}
|
||||
}
|
||||
|
||||
if len(gvks) == 0 {
|
||||
return fmt.Errorf("no registered kinds for %v", obj)
|
||||
}
|
||||
|
||||
7
tools/cache/controller_test.go
vendored
7
tools/cache/controller_test.go
vendored
@@ -242,15 +242,16 @@ func TestHammerController(t *testing.T) {
|
||||
currentNames := sets.String{}
|
||||
rs := rand.NewSource(rand.Int63())
|
||||
f := fuzz.New().NilChance(.5).NumElements(0, 2).RandSource(rs)
|
||||
r := rand.New(rs) // Mustn't use r and f concurrently!
|
||||
for i := 0; i < 100; i++ {
|
||||
var name string
|
||||
var isNew bool
|
||||
if currentNames.Len() == 0 || rand.Intn(3) == 1 {
|
||||
if currentNames.Len() == 0 || r.Intn(3) == 1 {
|
||||
f.Fuzz(&name)
|
||||
isNew = true
|
||||
} else {
|
||||
l := currentNames.List()
|
||||
name = l[rand.Intn(len(l))]
|
||||
name = l[r.Intn(len(l))]
|
||||
}
|
||||
|
||||
pod := &v1.Pod{}
|
||||
@@ -265,7 +266,7 @@ func TestHammerController(t *testing.T) {
|
||||
source.Add(pod)
|
||||
continue
|
||||
}
|
||||
switch rand.Intn(2) {
|
||||
switch r.Intn(2) {
|
||||
case 0:
|
||||
currentNames.Insert(name)
|
||||
source.Modify(pod)
|
||||
|
||||
2
tools/cache/fake_custom_store.go
vendored
2
tools/cache/fake_custom_store.go
vendored
@@ -25,7 +25,7 @@ type FakeCustomStore struct {
|
||||
ListKeysFunc func() []string
|
||||
GetFunc func(obj interface{}) (item interface{}, exists bool, err error)
|
||||
GetByKeyFunc func(key string) (item interface{}, exists bool, err error)
|
||||
ReplaceFunc func(list []interface{}, resourceVersion string) error
|
||||
ReplaceFunc func(list []interface{}, resourceVerion string) error
|
||||
ResyncFunc func() error
|
||||
}
|
||||
|
||||
|
||||
26
tools/cache/index.go
vendored
26
tools/cache/index.go
vendored
@@ -23,27 +23,17 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
// Indexer is a storage interface that lets you list objects using multiple indexing functions.
|
||||
// There are three kinds of strings here.
|
||||
// One is a storage key, as defined in the Store interface.
|
||||
// Another kind is a name of an index.
|
||||
// The third kind of string is an "indexed value", which is produced by an
|
||||
// IndexFunc and can be a field value or any other string computed from the object.
|
||||
// Indexer is a storage interface that lets you list objects using multiple indexing functions
|
||||
type Indexer interface {
|
||||
Store
|
||||
// Index returns the stored objects whose set of indexed values
|
||||
// intersects the set of indexed values of the given object, for
|
||||
// the named index
|
||||
// Retrieve list of objects that match on the named indexing function
|
||||
Index(indexName string, obj interface{}) ([]interface{}, error)
|
||||
// IndexKeys returns the storage keys of the stored objects whose
|
||||
// set of indexed values for the named index includes the given
|
||||
// indexed value
|
||||
IndexKeys(indexName, indexedValue string) ([]string, error)
|
||||
// ListIndexFuncValues returns all the indexed values of the given index
|
||||
// IndexKeys returns the set of keys that match on the named indexing function.
|
||||
IndexKeys(indexName, indexKey string) ([]string, error)
|
||||
// ListIndexFuncValues returns the list of generated values of an Index func
|
||||
ListIndexFuncValues(indexName string) []string
|
||||
// ByIndex returns the stored objects whose set of indexed values
|
||||
// for the named index includes the given indexed value
|
||||
ByIndex(indexName, indexedValue string) ([]interface{}, error)
|
||||
// ByIndex lists object that match on the named indexing function with the exact key
|
||||
ByIndex(indexName, indexKey string) ([]interface{}, error)
|
||||
// GetIndexer return the indexers
|
||||
GetIndexers() Indexers
|
||||
|
||||
@@ -52,7 +42,7 @@ type Indexer interface {
|
||||
AddIndexers(newIndexers Indexers) error
|
||||
}
|
||||
|
||||
// IndexFunc knows how to compute the set of indexed values for an object.
|
||||
// IndexFunc knows how to provide an indexed value for an object.
|
||||
type IndexFunc func(obj interface{}) ([]string, error)
|
||||
|
||||
// IndexFuncToKeyFuncAdapter adapts an indexFunc to a keyFunc. This is only useful if your index function returns
|
||||
|
||||
29
tools/cache/main_test.go
vendored
29
tools/cache/main_test.go
vendored
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 cache
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
2
tools/cache/mutation_detector.go
vendored
2
tools/cache/mutation_detector.go
vendored
@@ -114,7 +114,7 @@ func (d *defaultCacheMutationDetector) CompareObjects() {
|
||||
altered := false
|
||||
for i, obj := range d.cachedObjs {
|
||||
if !reflect.DeepEqual(obj.cached, obj.copied) {
|
||||
fmt.Printf("CACHE %s[%d] ALTERED!\n%v\n", d.name, i, diff.ObjectGoPrintSideBySide(obj.cached, obj.copied))
|
||||
fmt.Printf("CACHE %s[%d] ALTERED!\n%v\n", d.name, i, diff.ObjectDiff(obj.cached, obj.copied))
|
||||
altered = true
|
||||
}
|
||||
}
|
||||
|
||||
10
tools/cache/reflector.go
vendored
10
tools/cache/reflector.go
vendored
@@ -268,7 +268,8 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
// To reduce load on kube-apiserver on watch restarts, you may enable watch bookmarks.
|
||||
// Reflector doesn't assume bookmarks are returned at all (if the server do not support
|
||||
// watch bookmarks, it will ignore this field).
|
||||
AllowWatchBookmarks: true,
|
||||
// Disabled in Alpha release of watch bookmarks feature.
|
||||
AllowWatchBookmarks: false,
|
||||
}
|
||||
|
||||
w, err := r.listerWatcher.Watch(options)
|
||||
@@ -298,12 +299,7 @@ func (r *Reflector) ListAndWatch(stopCh <-chan struct{}) error {
|
||||
|
||||
if err := r.watchHandler(w, &resourceVersion, resyncerrc, stopCh); err != nil {
|
||||
if err != errorStopRequested {
|
||||
switch {
|
||||
case apierrs.IsResourceExpired(err):
|
||||
klog.V(4).Infof("%s: watch of %v ended with: %v", r.name, r.expectedType, err)
|
||||
default:
|
||||
klog.Warningf("%s: watch of %v ended with: %v", r.name, r.expectedType, err)
|
||||
}
|
||||
klog.Warningf("%s: watch of %v ended with: %v", r.name, r.expectedType, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
0
tools/cache/store.go
vendored
Normal file → Executable file
0
tools/cache/store.go
vendored
Normal file → Executable file
@@ -127,10 +127,6 @@ type ClientConfigLoadingRules struct {
|
||||
// DefaultClientConfig is an optional field indicating what rules to use to calculate a default configuration.
|
||||
// This should match the overrides passed in to ClientConfig loader.
|
||||
DefaultClientConfig ClientConfig
|
||||
|
||||
// WarnIfAllMissing indicates whether the configuration files pointed by KUBECONFIG environment variable are present or not.
|
||||
// In case of missing files, it warns the user about the missing files.
|
||||
WarnIfAllMissing bool
|
||||
}
|
||||
|
||||
// ClientConfigLoadingRules implements the ClientConfigLoader interface.
|
||||
@@ -140,23 +136,20 @@ var _ ClientConfigLoader = &ClientConfigLoadingRules{}
|
||||
// use this constructor
|
||||
func NewDefaultClientConfigLoadingRules() *ClientConfigLoadingRules {
|
||||
chain := []string{}
|
||||
warnIfAllMissing := false
|
||||
|
||||
envVarFiles := os.Getenv(RecommendedConfigPathEnvVar)
|
||||
if len(envVarFiles) != 0 {
|
||||
fileList := filepath.SplitList(envVarFiles)
|
||||
// prevent the same path load multiple times
|
||||
chain = append(chain, deduplicate(fileList)...)
|
||||
warnIfAllMissing = true
|
||||
|
||||
} else {
|
||||
chain = append(chain, RecommendedHomeFile)
|
||||
}
|
||||
|
||||
return &ClientConfigLoadingRules{
|
||||
Precedence: chain,
|
||||
MigrationRules: currentMigrationRules(),
|
||||
WarnIfAllMissing: warnIfAllMissing,
|
||||
Precedence: chain,
|
||||
MigrationRules: currentMigrationRules(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +172,6 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
|
||||
}
|
||||
|
||||
errlist := []error{}
|
||||
missingList := []string{}
|
||||
|
||||
kubeConfigFiles := []string{}
|
||||
|
||||
@@ -203,26 +195,18 @@ func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) {
|
||||
}
|
||||
|
||||
config, err := LoadFromFile(filename)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
// skip missing files
|
||||
// Add to the missing list to produce a warning
|
||||
missingList = append(missingList, filename)
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errlist = append(errlist, fmt.Errorf("error loading config file \"%s\": %v", filename, err))
|
||||
errlist = append(errlist, fmt.Errorf("Error loading config file \"%s\": %v", filename, err))
|
||||
continue
|
||||
}
|
||||
|
||||
kubeconfigs = append(kubeconfigs, config)
|
||||
}
|
||||
|
||||
if rules.WarnIfAllMissing && len(missingList) > 0 && len(kubeconfigs) == 0 {
|
||||
klog.Warningf("Config not found: %s", strings.Join(missingList, ", "))
|
||||
}
|
||||
|
||||
// first merge all of our maps
|
||||
mapConfig := clientcmdapi.NewConfig()
|
||||
|
||||
@@ -483,7 +467,7 @@ func ResolveLocalPaths(config *clientcmdapi.Config) error {
|
||||
}
|
||||
base, err := filepath.Abs(filepath.Dir(cluster.LocationOfOrigin))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not determine the absolute path of config file %s: %v", cluster.LocationOfOrigin, err)
|
||||
return fmt.Errorf("Could not determine the absolute path of config file %s: %v", cluster.LocationOfOrigin, err)
|
||||
}
|
||||
|
||||
if err := ResolvePaths(GetClusterFileReferences(cluster), base); err != nil {
|
||||
@@ -496,7 +480,7 @@ func ResolveLocalPaths(config *clientcmdapi.Config) error {
|
||||
}
|
||||
base, err := filepath.Abs(filepath.Dir(authInfo.LocationOfOrigin))
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not determine the absolute path of config file %s: %v", authInfo.LocationOfOrigin, err)
|
||||
return fmt.Errorf("Could not determine the absolute path of config file %s: %v", authInfo.LocationOfOrigin, err)
|
||||
}
|
||||
|
||||
if err := ResolvePaths(GetAuthInfoFileReferences(authInfo), base); err != nil {
|
||||
|
||||
@@ -250,6 +250,8 @@ func validateAuthInfo(authInfoName string, authInfo clientcmdapi.AuthInfo) []err
|
||||
for _, v := range authInfo.Exec.Env {
|
||||
if len(v.Name) == 0 {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("env variable name must be specified for %v to use exec authentication plugin", authInfoName))
|
||||
} else if len(v.Value) == 0 {
|
||||
validationErrors = append(validationErrors, fmt.Errorf("env variable %s value must be specified for %v to use exec authentication plugin", v.Name, authInfoName))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,19 +443,22 @@ func TestValidateAuthInfoExecWithAuthProvider(t *testing.T) {
|
||||
test.testConfig(t)
|
||||
}
|
||||
|
||||
func TestValidateAuthInfoExecNoEnv(t *testing.T) {
|
||||
func TestValidateAuthInfoExecInvalidEnv(t *testing.T) {
|
||||
config := clientcmdapi.NewConfig()
|
||||
config.AuthInfos["user"] = &clientcmdapi.AuthInfo{
|
||||
Exec: &clientcmdapi.ExecConfig{
|
||||
Command: "/bin/example",
|
||||
APIVersion: "clientauthentication.k8s.io/v1alpha1",
|
||||
Env: []clientcmdapi.ExecEnvVar{
|
||||
{Name: "foo", Value: ""},
|
||||
{Name: "foo"}, // No value
|
||||
},
|
||||
},
|
||||
}
|
||||
test := configValidationTest{
|
||||
config: config,
|
||||
expectedErrorSubstring: []string{
|
||||
"env variable foo value must be specified for user to use exec authentication plugin",
|
||||
},
|
||||
}
|
||||
|
||||
test.testAuthInfo("user", t)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- yastij
|
||||
- wojtek-t
|
||||
reviewers:
|
||||
- yastij
|
||||
- wojtek-t
|
||||
@@ -271,9 +271,9 @@ func getKey(event *v1beta1.Event) eventKey {
|
||||
return key
|
||||
}
|
||||
|
||||
// StartEventWatcher starts sending events received from this EventBroadcaster to the given event handler function.
|
||||
// startEventWatcher starts sending events received from this EventBroadcaster to the given event handler function.
|
||||
// The return value is used to stop recording
|
||||
func (e *eventBroadcasterImpl) StartEventWatcher(eventHandler func(event runtime.Object)) func() {
|
||||
func (e *eventBroadcasterImpl) startEventWatcher(eventHandler func(event runtime.Object)) func() {
|
||||
watcher := e.Watch()
|
||||
go func() {
|
||||
defer utilruntime.HandleCrash()
|
||||
@@ -304,7 +304,7 @@ func (e *eventBroadcasterImpl) StartRecordingToSink(stopCh <-chan struct{}) {
|
||||
}
|
||||
e.recordToSink(event, clock.RealClock{})
|
||||
}
|
||||
stopWatcher := e.StartEventWatcher(eventHandler)
|
||||
stopWatcher := e.startEventWatcher(eventHandler)
|
||||
go func() {
|
||||
<-stopCh
|
||||
stopWatcher()
|
||||
|
||||
@@ -51,7 +51,7 @@ func (recorder *recorderImpl) Eventf(regarding runtime.Object, related runtime.O
|
||||
}
|
||||
refRelated, err := reference.GetReference(recorder.scheme, related)
|
||||
if err != nil {
|
||||
klog.V(9).Infof("Could not construct reference to: '%#v' due to: '%v'.", related, err)
|
||||
klog.Errorf("Could not construct reference to: '%#v' due to: '%v'.", related, err)
|
||||
}
|
||||
if !util.ValidateEventType(eventtype) {
|
||||
klog.Errorf("Unsupported event type: '%v'", eventtype)
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
Copyright 2019 The Kubernetes 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 events
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// FakeRecorder is used as a fake during tests. It is thread safe. It is usable
|
||||
// when created manually and not by NewFakeRecorder, however all events may be
|
||||
// thrown away in this case.
|
||||
type FakeRecorder struct {
|
||||
Events chan string
|
||||
}
|
||||
|
||||
// Eventf emits an event
|
||||
func (f *FakeRecorder) Eventf(regarding runtime.Object, related runtime.Object, eventtype, reason, action, note string, args ...interface{}) {
|
||||
if f.Events != nil {
|
||||
f.Events <- fmt.Sprintf(eventtype+" "+reason+" "+note, args...)
|
||||
}
|
||||
}
|
||||
|
||||
// NewFakeRecorder creates new fake event recorder with event channel with
|
||||
// buffer of given size.
|
||||
func NewFakeRecorder(bufferSize int) *FakeRecorder {
|
||||
return &FakeRecorder{
|
||||
Events: make(chan string, bufferSize),
|
||||
}
|
||||
}
|
||||
@@ -45,12 +45,6 @@ type EventBroadcaster interface {
|
||||
// NewRecorder returns an EventRecorder that can be used to send events to this EventBroadcaster
|
||||
// with the event source set to the given event source.
|
||||
NewRecorder(scheme *runtime.Scheme, reportingController string) EventRecorder
|
||||
|
||||
// StartEventWatcher enables you to watch for emitted events without usage
|
||||
// of StartRecordingToSink. This lets you also process events in a custom way (e.g. in tests).
|
||||
// NOTE: events received on your eventHandler should be copied before being used.
|
||||
// TODO: figure out if this can be removed.
|
||||
StartEventWatcher(eventHandler func(event runtime.Object)) func()
|
||||
}
|
||||
|
||||
// EventSink knows how to store events (client-go implements it.)
|
||||
|
||||
@@ -76,7 +76,7 @@ func TestLeaderElectionHealthChecker(t *testing.T) {
|
||||
elector: nil,
|
||||
},
|
||||
{
|
||||
description: "call check when the lease is far expired",
|
||||
description: "call check when the the lease is far expired",
|
||||
expected: fmt.Errorf("failed election to renew leadership on lease %s", "foo"),
|
||||
adaptorTimeout: time.Second * 20,
|
||||
elector: &LeaderElector{
|
||||
@@ -93,7 +93,7 @@ func TestLeaderElectionHealthChecker(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "call check when the lease is far expired but held by another server",
|
||||
description: "call check when the the lease is far expired but held by another server",
|
||||
expected: nil,
|
||||
adaptorTimeout: time.Second * 20,
|
||||
elector: &LeaderElector{
|
||||
@@ -110,7 +110,7 @@ func TestLeaderElectionHealthChecker(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "call check when the lease is not expired",
|
||||
description: "call check when the the lease is not expired",
|
||||
expected: nil,
|
||||
adaptorTimeout: time.Second * 20,
|
||||
elector: &LeaderElector{
|
||||
@@ -127,7 +127,7 @@ func TestLeaderElectionHealthChecker(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "call check when the lease is expired but inside the timeout",
|
||||
description: "call check when the the lease is expired but inside the timeout",
|
||||
expected: nil,
|
||||
adaptorTimeout: time.Second * 20,
|
||||
elector: &LeaderElector{
|
||||
|
||||
@@ -90,20 +90,20 @@ func parsePorts(ports []string) ([]ForwardedPort, error) {
|
||||
}
|
||||
remoteString = parts[1]
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid port format '%s'", portString)
|
||||
return nil, fmt.Errorf("Invalid port format '%s'", portString)
|
||||
}
|
||||
|
||||
localPort, err := strconv.ParseUint(localString, 10, 16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing local port '%s': %s", localString, err)
|
||||
return nil, fmt.Errorf("Error parsing local port '%s': %s", localString, err)
|
||||
}
|
||||
|
||||
remotePort, err := strconv.ParseUint(remoteString, 10, 16)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing remote port '%s': %s", remoteString, err)
|
||||
return nil, fmt.Errorf("Error parsing remote port '%s': %s", remoteString, err)
|
||||
}
|
||||
if remotePort == 0 {
|
||||
return nil, fmt.Errorf("remote port must be > 0")
|
||||
return nil, fmt.Errorf("Remote port must be > 0")
|
||||
}
|
||||
|
||||
forwards = append(forwards, ForwardedPort{uint16(localPort), uint16(remotePort)})
|
||||
@@ -159,14 +159,14 @@ func New(dialer httpstream.Dialer, ports []string, stopChan <-chan struct{}, rea
|
||||
// NewOnAddresses creates a new PortForwarder with custom listen addresses.
|
||||
func NewOnAddresses(dialer httpstream.Dialer, addresses []string, ports []string, stopChan <-chan struct{}, readyChan chan struct{}, out, errOut io.Writer) (*PortForwarder, error) {
|
||||
if len(addresses) == 0 {
|
||||
return nil, errors.New("you must specify at least 1 address")
|
||||
return nil, errors.New("You must specify at least 1 address")
|
||||
}
|
||||
parsedAddresses, err := parseAddresses(addresses)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ports) == 0 {
|
||||
return nil, errors.New("you must specify at least 1 port")
|
||||
return nil, errors.New("You must specify at least 1 port")
|
||||
}
|
||||
parsedPorts, err := parsePorts(ports)
|
||||
if err != nil {
|
||||
@@ -219,7 +219,7 @@ func (pf *PortForwarder) forward() error {
|
||||
}
|
||||
|
||||
if !listenSuccess {
|
||||
return fmt.Errorf("unable to listen on any of the requested ports: %v", pf.ports)
|
||||
return fmt.Errorf("Unable to listen on any of the requested ports: %v", pf.ports)
|
||||
}
|
||||
|
||||
if pf.Ready != nil {
|
||||
@@ -277,7 +277,7 @@ func (pf *PortForwarder) listenOnPortAndAddress(port *ForwardedPort, protocol st
|
||||
func (pf *PortForwarder) getListener(protocol string, hostname string, port *ForwardedPort) (net.Listener, error) {
|
||||
listener, err := net.Listen(protocol, net.JoinHostPort(hostname, strconv.Itoa(int(port.Local))))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create listener: Error %s", err)
|
||||
return nil, fmt.Errorf("Unable to create listener: Error %s", err)
|
||||
}
|
||||
listenerAddress := listener.Addr().String()
|
||||
host, localPort, _ := net.SplitHostPort(listenerAddress)
|
||||
@@ -285,7 +285,7 @@ func (pf *PortForwarder) getListener(protocol string, hostname string, port *For
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(pf.out, "Failed to forward from %s:%d -> %d\n", hostname, localPortUInt, port.Remote)
|
||||
return nil, fmt.Errorf("error parsing local port: %s from %s (%s)", err, listenerAddress, host)
|
||||
return nil, fmt.Errorf("Error parsing local port: %s from %s (%s)", err, listenerAddress, host)
|
||||
}
|
||||
port.Local = uint16(localPortUInt)
|
||||
if pf.out != nil {
|
||||
@@ -303,7 +303,7 @@ func (pf *PortForwarder) waitForConnection(listener net.Listener, port Forwarded
|
||||
if err != nil {
|
||||
// TODO consider using something like https://github.com/hydrogen18/stoppableListener?
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "use of closed network connection") {
|
||||
runtime.HandleError(fmt.Errorf("error accepting connection on port %d: %v", port.Local, err))
|
||||
runtime.HandleError(fmt.Errorf("Error accepting connection on port %d: %v", port.Local, err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -162,14 +162,17 @@ type eventBroadcasterImpl struct {
|
||||
// The return value can be ignored or used to stop recording, if desired.
|
||||
// TODO: make me an object with parameterizable queue length and retry interval
|
||||
func (eventBroadcaster *eventBroadcasterImpl) StartRecordingToSink(sink EventSink) watch.Interface {
|
||||
// The default math/rand package functions aren't thread safe, so create a
|
||||
// new Rand object for each StartRecording call.
|
||||
randGen := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
eventCorrelator := NewEventCorrelatorWithOptions(eventBroadcaster.options)
|
||||
return eventBroadcaster.StartEventWatcher(
|
||||
func(event *v1.Event) {
|
||||
recordToSink(sink, event, eventCorrelator, eventBroadcaster.sleepDuration)
|
||||
recordToSink(sink, event, eventCorrelator, randGen, eventBroadcaster.sleepDuration)
|
||||
})
|
||||
}
|
||||
|
||||
func recordToSink(sink EventSink, event *v1.Event, eventCorrelator *EventCorrelator, sleepDuration time.Duration) {
|
||||
func recordToSink(sink EventSink, event *v1.Event, eventCorrelator *EventCorrelator, randGen *rand.Rand, sleepDuration time.Duration) {
|
||||
// Make a copy before modification, because there could be multiple listeners.
|
||||
// Events are safe to copy like this.
|
||||
eventCopy := *event
|
||||
@@ -194,7 +197,7 @@ func recordToSink(sink EventSink, event *v1.Event, eventCorrelator *EventCorrela
|
||||
// Randomize the first sleep so that various clients won't all be
|
||||
// synced up if the master goes down.
|
||||
if tries == 1 {
|
||||
time.Sleep(time.Duration(float64(sleepDuration) * rand.Float64()))
|
||||
time.Sleep(time.Duration(float64(sleepDuration) * randGen.Float64()))
|
||||
} else {
|
||||
time.Sleep(sleepDuration)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package record
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"testing"
|
||||
@@ -152,7 +153,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -161,7 +162,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -180,7 +181,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
Reason: "Killed",
|
||||
Message: "some other verbose message: 1",
|
||||
@@ -188,7 +189,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -207,7 +208,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -216,7 +217,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
@@ -235,7 +236,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "differentUid",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -244,7 +245,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -263,7 +264,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -272,7 +273,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 3,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
@@ -291,7 +292,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "differentUid",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
@@ -300,7 +301,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -319,7 +320,7 @@ func TestEventf(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "differentUid",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
@@ -328,7 +329,7 @@ func TestEventf(t *testing.T) {
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
},
|
||||
}
|
||||
@@ -416,6 +417,7 @@ func TestWriteEventError(t *testing.T) {
|
||||
|
||||
clock := clock.IntervalClock{Time: time.Now(), Duration: time.Second}
|
||||
eventCorrelator := NewEventCorrelator(&clock)
|
||||
randGen := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
for caseName, ent := range table {
|
||||
attempts := 0
|
||||
@@ -429,7 +431,7 @@ func TestWriteEventError(t *testing.T) {
|
||||
},
|
||||
}
|
||||
ev := &v1.Event{}
|
||||
recordToSink(sink, ev, eventCorrelator, 0)
|
||||
recordToSink(sink, ev, eventCorrelator, randGen, 0)
|
||||
if attempts != ent.attemptsWanted {
|
||||
t.Errorf("case %v: wanted %d, got %d attempts", caseName, ent.attemptsWanted, attempts)
|
||||
}
|
||||
@@ -439,6 +441,7 @@ func TestWriteEventError(t *testing.T) {
|
||||
func TestUpdateExpiredEvent(t *testing.T) {
|
||||
clock := clock.IntervalClock{Time: time.Now(), Duration: time.Second}
|
||||
eventCorrelator := NewEventCorrelator(&clock)
|
||||
randGen := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
|
||||
var createdEvent *v1.Event
|
||||
|
||||
@@ -459,7 +462,7 @@ func TestUpdateExpiredEvent(t *testing.T) {
|
||||
ev := &v1.Event{}
|
||||
ev.ResourceVersion = "updated-resource-version"
|
||||
ev.Count = 2
|
||||
recordToSink(sink, ev, eventCorrelator, 0)
|
||||
recordToSink(sink, ev, eventCorrelator, randGen, 0)
|
||||
|
||||
if createdEvent == nil {
|
||||
t.Error("Event did not get created after patch failed")
|
||||
@@ -506,7 +509,7 @@ func TestLotsOfEvents(t *testing.T) {
|
||||
Name: fmt.Sprintf("foo-%v", i),
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
}
|
||||
// we need to vary the reason to prevent aggregation
|
||||
go recorder.Eventf(ref, v1.EventTypeNormal, "Reason-"+string(i), strconv.Itoa(i))
|
||||
@@ -564,7 +567,7 @@ func TestEventfNoNamespace(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -573,7 +576,7 @@ func TestEventfNoNamespace(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
}
|
||||
@@ -674,7 +677,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -683,7 +686,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -702,7 +705,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
},
|
||||
Reason: "Killed",
|
||||
Message: "some other verbose message: 1",
|
||||
@@ -710,7 +713,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:""}): type: 'Normal' reason: 'Killed' some other verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -729,7 +732,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -738,7 +741,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
@@ -757,7 +760,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "differentUid",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -766,7 +769,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -785,7 +788,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "bar",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[2]",
|
||||
},
|
||||
Reason: "Started",
|
||||
@@ -794,7 +797,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 3,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"bar", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[2]"}): type: 'Normal' reason: 'Started' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
},
|
||||
{
|
||||
@@ -813,7 +816,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "differentUid",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
@@ -822,7 +825,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 1,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: false,
|
||||
},
|
||||
{
|
||||
@@ -841,7 +844,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Name: "foo",
|
||||
Namespace: "baz",
|
||||
UID: "differentUid",
|
||||
APIVersion: "version",
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.containers[3]",
|
||||
},
|
||||
Reason: "Stopped",
|
||||
@@ -850,7 +853,7 @@ func TestMultiSinkCache(t *testing.T) {
|
||||
Count: 2,
|
||||
Type: v1.EventTypeNormal,
|
||||
},
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"version", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectLog: `Event(v1.ObjectReference{Kind:"Pod", Namespace:"baz", Name:"foo", UID:"differentUid", APIVersion:"v1", ResourceVersion:"", FieldPath:"spec.containers[3]"}): type: 'Normal' reason: 'Stopped' some verbose message: 1`,
|
||||
expectUpdate: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 record
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -19,8 +19,6 @@ package reference
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
@@ -30,8 +28,7 @@ import (
|
||||
|
||||
var (
|
||||
// Errors that could be returned by GetReference.
|
||||
ErrNilObject = errors.New("can't reference a nil object")
|
||||
ErrNoSelfLink = errors.New("selfLink was empty, can't make reference")
|
||||
ErrNilObject = errors.New("can't reference a nil object")
|
||||
)
|
||||
|
||||
// GetReference returns an ObjectReference which refers to the given
|
||||
@@ -47,20 +44,6 @@ func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*v1.ObjectReferen
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||
|
||||
// if the object referenced is actually persisted, we can just get kind from meta
|
||||
// if we are building an object reference to something not yet persisted, we should fallback to scheme
|
||||
kind := gvk.Kind
|
||||
if len(kind) == 0 {
|
||||
// TODO: this is wrong
|
||||
gvks, _, err := scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kind = gvks[0].Kind
|
||||
}
|
||||
|
||||
// An object that implements only List has enough metadata to build a reference
|
||||
var listMeta metav1.Common
|
||||
objectMeta, err := meta.Accessor(obj)
|
||||
@@ -73,29 +56,29 @@ func GetReference(scheme *runtime.Scheme, obj runtime.Object) (*v1.ObjectReferen
|
||||
listMeta = objectMeta
|
||||
}
|
||||
|
||||
// if the object referenced is actually persisted, we can also get version from meta
|
||||
version := gvk.GroupVersion().String()
|
||||
if len(version) == 0 {
|
||||
selfLink := listMeta.GetSelfLink()
|
||||
if len(selfLink) == 0 {
|
||||
return nil, ErrNoSelfLink
|
||||
}
|
||||
selfLinkUrl, err := url.Parse(selfLink)
|
||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||
|
||||
// If object meta doesn't contain data about kind and/or version,
|
||||
// we are falling back to scheme.
|
||||
//
|
||||
// TODO: This doesn't work for CRDs, which are not registered in scheme.
|
||||
if gvk.Empty() {
|
||||
gvks, _, err := scheme.ObjectKinds(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// example paths: /<prefix>/<version>/*
|
||||
parts := strings.Split(selfLinkUrl.Path, "/")
|
||||
if len(parts) < 4 {
|
||||
return nil, fmt.Errorf("unexpected self link format: '%v'; got version '%v'", selfLink, version)
|
||||
}
|
||||
if parts[1] == "api" {
|
||||
version = parts[2]
|
||||
} else {
|
||||
version = parts[2] + "/" + parts[3]
|
||||
if len(gvks) == 0 || gvks[0].Empty() {
|
||||
return nil, fmt.Errorf("unexpected gvks registered for object %T: %v", obj, gvks)
|
||||
}
|
||||
// TODO: The same object can be registered for multiple group versions
|
||||
// (although in practise this doesn't seem to be used).
|
||||
// In such case, the version set may not be correct.
|
||||
gvk = gvks[0]
|
||||
}
|
||||
|
||||
kind := gvk.Kind
|
||||
version := gvk.GroupVersion().String()
|
||||
|
||||
// only has list metadata
|
||||
if objectMeta == nil {
|
||||
return &v1.ObjectReference{
|
||||
|
||||
@@ -37,29 +37,31 @@ func TestGetReferenceRefVersion(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input *TestRuntimeObj
|
||||
groupVersion schema.GroupVersion
|
||||
expectedRefVersion string
|
||||
}{
|
||||
{
|
||||
name: "api from selflink",
|
||||
name: "v1 GV from scheme",
|
||||
input: &TestRuntimeObj{
|
||||
ObjectMeta: metav1.ObjectMeta{SelfLink: "/api/v1/namespaces"},
|
||||
ObjectMeta: metav1.ObjectMeta{SelfLink: "/bad-selflink/unused"},
|
||||
},
|
||||
groupVersion: schema.GroupVersion{Group: "", Version: "v1"},
|
||||
expectedRefVersion: "v1",
|
||||
},
|
||||
{
|
||||
name: "foo.group/v3 from selflink",
|
||||
name: "foo.group/v3 GV from scheme",
|
||||
input: &TestRuntimeObj{
|
||||
ObjectMeta: metav1.ObjectMeta{SelfLink: "/apis/foo.group/v3/namespaces"},
|
||||
ObjectMeta: metav1.ObjectMeta{SelfLink: "/bad-selflink/unused"},
|
||||
},
|
||||
groupVersion: schema.GroupVersion{Group: "foo.group", Version: "v3"},
|
||||
expectedRefVersion: "foo.group/v3",
|
||||
},
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypes(schema.GroupVersion{Group: "this", Version: "is ignored"}, &TestRuntimeObj{})
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
scheme.AddKnownTypes(test.groupVersion, &TestRuntimeObj{})
|
||||
ref, err := GetReference(scheme, test.input)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
||||
@@ -411,7 +411,7 @@ func (m *manager) rotateCerts() (bool, error) {
|
||||
// is a remainder after the old design using raw watch wrapped with backoff.
|
||||
crtPEM, err := csr.WaitForCertificate(ctx, client, req)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("certificate request was not signed: %v", err))
|
||||
utilruntime.HandleError(fmt.Errorf("Certificate request was not signed: %v", err))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -981,7 +981,7 @@ func (c fakeClient) Create(*certificates.CertificateSigningRequest) (*certificat
|
||||
if c.err != nil {
|
||||
return nil, c.err
|
||||
}
|
||||
return nil, fmt.Errorf("create error")
|
||||
return nil, fmt.Errorf("Create error")
|
||||
}
|
||||
csrReply := certificates.CertificateSigningRequest{}
|
||||
csrReply.UID = "fake-uid"
|
||||
@@ -993,7 +993,7 @@ func (c fakeClient) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
if c.err != nil {
|
||||
return nil, c.err
|
||||
}
|
||||
return nil, fmt.Errorf("watch error")
|
||||
return nil, fmt.Errorf("Watch error")
|
||||
}
|
||||
return &fakeWatch{
|
||||
failureType: c.failureType,
|
||||
|
||||
@@ -30,7 +30,7 @@ type backoffEntry struct {
|
||||
}
|
||||
|
||||
type Backoff struct {
|
||||
sync.RWMutex
|
||||
sync.Mutex
|
||||
Clock clock.Clock
|
||||
defaultDuration time.Duration
|
||||
maxDuration time.Duration
|
||||
@@ -57,8 +57,8 @@ func NewBackOff(initial, max time.Duration) *Backoff {
|
||||
|
||||
// Get the current backoff Duration
|
||||
func (p *Backoff) Get(id string) time.Duration {
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
var delay time.Duration
|
||||
entry, ok := p.perItemBackoff[id]
|
||||
if ok {
|
||||
@@ -90,8 +90,8 @@ func (p *Backoff) Reset(id string) {
|
||||
|
||||
// Returns True if the elapsed time since eventTime is smaller than the current backoff window
|
||||
func (p *Backoff) IsInBackOffSince(id string, eventTime time.Time) bool {
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
entry, ok := p.perItemBackoff[id]
|
||||
if !ok {
|
||||
return false
|
||||
@@ -104,8 +104,8 @@ func (p *Backoff) IsInBackOffSince(id string, eventTime time.Time) bool {
|
||||
|
||||
// Returns True if time since lastupdate is less than the current backoff window.
|
||||
func (p *Backoff) IsInBackOffSinceUpdate(id string, eventTime time.Time) bool {
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
entry, ok := p.perItemBackoff[id]
|
||||
if !ok {
|
||||
return false
|
||||
|
||||
@@ -17,8 +17,6 @@ limitations under the License.
|
||||
package flowcontrol
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -35,8 +33,6 @@ type RateLimiter interface {
|
||||
Stop()
|
||||
// QPS returns QPS of this rate limiter
|
||||
QPS() float32
|
||||
// Wait returns nil if a token is taken before the Context is done.
|
||||
Wait(ctx context.Context) error
|
||||
}
|
||||
|
||||
type tokenBucketRateLimiter struct {
|
||||
@@ -102,10 +98,6 @@ func (t *tokenBucketRateLimiter) QPS() float32 {
|
||||
return t.qps
|
||||
}
|
||||
|
||||
func (t *tokenBucketRateLimiter) Wait(ctx context.Context) error {
|
||||
return t.limiter.Wait(ctx)
|
||||
}
|
||||
|
||||
type fakeAlwaysRateLimiter struct{}
|
||||
|
||||
func NewFakeAlwaysRateLimiter() RateLimiter {
|
||||
@@ -124,10 +116,6 @@ func (t *fakeAlwaysRateLimiter) QPS() float32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (t *fakeAlwaysRateLimiter) Wait(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type fakeNeverRateLimiter struct {
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
@@ -153,7 +141,3 @@ func (t *fakeNeverRateLimiter) Accept() {
|
||||
func (t *fakeNeverRateLimiter) QPS() float32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (t *fakeNeverRateLimiter) Wait(ctx context.Context) error {
|
||||
return errors.New("can not be accept")
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ limitations under the License.
|
||||
package flowcontrol
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -153,21 +151,3 @@ func TestNeverFake(t *testing.T) {
|
||||
t.Error("Stop should make Accept unblock in NeverFake.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWait(t *testing.T) {
|
||||
r := NewTokenBucketRateLimiter(0.0001, 1)
|
||||
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancelFn()
|
||||
if err := r.Wait(ctx); err != nil {
|
||||
t.Errorf("unexpected wait failed, err: %v", err)
|
||||
}
|
||||
|
||||
ctx2, cancelFn2 := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancelFn2()
|
||||
if err := r.Wait(ctx2); err == nil {
|
||||
t.Errorf("unexpected wait success")
|
||||
} else {
|
||||
t.Log(fmt.Sprintf("wait err: %v", err))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,75 +18,30 @@ package homedir
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// HomeDir returns the home directory for the current user.
|
||||
// On Windows:
|
||||
// 1. the first of %HOME%, %HOMEDRIVE%%HOMEPATH%, %USERPROFILE% containing a `.kube\config` file is returned.
|
||||
// 2. if none of those locations contain a `.kube\config` file, the first of %HOME%, %USERPROFILE%, %HOMEDRIVE%%HOMEPATH% that exists and is writeable is returned.
|
||||
// 3. if none of those locations are writeable, the first of %HOME%, %USERPROFILE%, %HOMEDRIVE%%HOMEPATH% that exists is returned.
|
||||
// 4. if none of those locations exists, the first of %HOME%, %USERPROFILE%, %HOMEDRIVE%%HOMEPATH% that is set is returned.
|
||||
// HomeDir returns the home directory for the current user
|
||||
func HomeDir() string {
|
||||
if runtime.GOOS == "windows" {
|
||||
home := os.Getenv("HOME")
|
||||
homeDriveHomePath := ""
|
||||
|
||||
// First prefer the HOME environmental variable
|
||||
if home := os.Getenv("HOME"); len(home) > 0 {
|
||||
if _, err := os.Stat(home); err == nil {
|
||||
return home
|
||||
}
|
||||
}
|
||||
if homeDrive, homePath := os.Getenv("HOMEDRIVE"), os.Getenv("HOMEPATH"); len(homeDrive) > 0 && len(homePath) > 0 {
|
||||
homeDriveHomePath = homeDrive + homePath
|
||||
}
|
||||
userProfile := os.Getenv("USERPROFILE")
|
||||
|
||||
// Return first of %HOME%, %HOMEDRIVE%/%HOMEPATH%, %USERPROFILE% that contains a `.kube\config` file.
|
||||
// %HOMEDRIVE%/%HOMEPATH% is preferred over %USERPROFILE% for backwards-compatibility.
|
||||
for _, p := range []string{home, homeDriveHomePath, userProfile} {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(p, ".kube", "config")); err != nil {
|
||||
continue
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
firstSetPath := ""
|
||||
firstExistingPath := ""
|
||||
|
||||
// Prefer %USERPROFILE% over %HOMEDRIVE%/%HOMEPATH% for compatibility with other auth-writing tools
|
||||
for _, p := range []string{home, userProfile, homeDriveHomePath} {
|
||||
if len(p) == 0 {
|
||||
continue
|
||||
}
|
||||
if len(firstSetPath) == 0 {
|
||||
// remember the first path that is set
|
||||
firstSetPath = p
|
||||
}
|
||||
info, err := os.Stat(p)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if len(firstExistingPath) == 0 {
|
||||
// remember the first path that exists
|
||||
firstExistingPath = p
|
||||
}
|
||||
if info.IsDir() && info.Mode().Perm()&(1<<(uint(7))) != 0 {
|
||||
// return first path that is writeable
|
||||
return p
|
||||
homeDir := homeDrive + homePath
|
||||
if _, err := os.Stat(homeDir); err == nil {
|
||||
return homeDir
|
||||
}
|
||||
}
|
||||
|
||||
// If none are writeable, return first location that exists
|
||||
if len(firstExistingPath) > 0 {
|
||||
return firstExistingPath
|
||||
if userProfile := os.Getenv("USERPROFILE"); len(userProfile) > 0 {
|
||||
if _, err := os.Stat(userProfile); err == nil {
|
||||
return userProfile
|
||||
}
|
||||
}
|
||||
|
||||
// If none exist, return first location that is set
|
||||
if len(firstSetPath) > 0 {
|
||||
return firstSetPath
|
||||
}
|
||||
|
||||
// We've got nothing
|
||||
return ""
|
||||
}
|
||||
return os.Getenv("HOME")
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ var DefaultBackoff = wait.Backoff{
|
||||
Jitter: 0.1,
|
||||
}
|
||||
|
||||
// OnError executes the provided function repeatedly, retrying if the server returns a specified
|
||||
// error. Callers should preserve previous executions if they wish to retry changes. It performs an
|
||||
// RetryConflict executes the provided function repeatedly, retrying if the server returns a conflicting
|
||||
// write. Callers should preserve previous executions if they wish to retry changes. It performs an
|
||||
// exponential backoff.
|
||||
//
|
||||
// var pod *api.Pod
|
||||
// err := retry.OnError(DefaultBackoff, errors.IsConflict, func() (err error) {
|
||||
// err := RetryOnConflict(DefaultBackoff, func() (err error) {
|
||||
// pod, err = c.Pods("mynamespace").UpdateStatus(podStatus)
|
||||
// return
|
||||
// })
|
||||
@@ -58,14 +58,14 @@ var DefaultBackoff = wait.Backoff{
|
||||
// ...
|
||||
//
|
||||
// TODO: Make Backoff an interface?
|
||||
func OnError(backoff wait.Backoff, errorFunc func(error) bool, fn func() error) error {
|
||||
func RetryOnConflict(backoff wait.Backoff, fn func() error) error {
|
||||
var lastConflictErr error
|
||||
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
err := fn()
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
case errorFunc(err):
|
||||
case errors.IsConflict(err):
|
||||
lastConflictErr = err
|
||||
return false, nil
|
||||
default:
|
||||
@@ -77,8 +77,3 @@ func OnError(backoff wait.Backoff, errorFunc func(error) bool, fn func() error)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// RetryOnConflict executes the function function repeatedly, retrying if the server returns a conflicting
|
||||
func RetryOnConflict(backoff wait.Backoff, fn func() error) error {
|
||||
return OnError(backoff, errors.IsConflict, fn)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ func MkTmpdir(prefix string) (string, error) {
|
||||
return tmpDir, nil
|
||||
}
|
||||
|
||||
// MkTmpdirOrDie does the same work as "MkTmpdir", except in case of
|
||||
// MkTmpdir does the same work as "MkTmpdir", except in case of
|
||||
// errors, it'll trigger a panic.
|
||||
func MkTmpdirOrDie(prefix string) string {
|
||||
tmpDir, err := MkTmpdir(prefix)
|
||||
|
||||
@@ -44,12 +44,13 @@ func NewNamedDelayingQueue(name string) DelayingInterface {
|
||||
|
||||
func newDelayingQueue(clock clock.Clock, name string) DelayingInterface {
|
||||
ret := &delayingType{
|
||||
Interface: NewNamed(name),
|
||||
clock: clock,
|
||||
heartbeat: clock.NewTicker(maxWait),
|
||||
stopCh: make(chan struct{}),
|
||||
waitingForAddCh: make(chan *waitFor, 1000),
|
||||
metrics: newRetryMetrics(name),
|
||||
Interface: NewNamed(name),
|
||||
clock: clock,
|
||||
heartbeat: clock.NewTicker(maxWait),
|
||||
stopCh: make(chan struct{}),
|
||||
waitingForAddCh: make(chan *waitFor, 1000),
|
||||
metrics: newRetryMetrics(name),
|
||||
deprecatedMetrics: newDeprecatedRetryMetrics(name),
|
||||
}
|
||||
|
||||
go ret.waitingLoop()
|
||||
@@ -76,7 +77,8 @@ type delayingType struct {
|
||||
waitingForAddCh chan *waitFor
|
||||
|
||||
// metrics counts the number of retries
|
||||
metrics retryMetrics
|
||||
metrics retryMetrics
|
||||
deprecatedMetrics retryMetrics
|
||||
}
|
||||
|
||||
// waitFor holds the data to add and the time it should be added
|
||||
@@ -152,6 +154,7 @@ func (q *delayingType) AddAfter(item interface{}, duration time.Duration) {
|
||||
}
|
||||
|
||||
q.metrics.retry()
|
||||
q.deprecatedMetrics.retry()
|
||||
|
||||
// immediately add things with no delay
|
||||
if duration <= 0 {
|
||||
|
||||
@@ -216,13 +216,15 @@ func TestCopyShifting(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkDelayingQueue_AddAfter(b *testing.B) {
|
||||
r := rand.New(rand.NewSource(time.Now().Unix()))
|
||||
|
||||
fakeClock := clock.NewFakeClock(time.Now())
|
||||
q := newDelayingQueue(fakeClock, "")
|
||||
|
||||
// Add items
|
||||
for n := 0; n < b.N; n++ {
|
||||
data := fmt.Sprintf("%d", n)
|
||||
q.AddAfter(data, time.Duration(rand.Int63n(int64(10*time.Minute))))
|
||||
q.AddAfter(data, time.Duration(r.Int63n(int64(10*time.Minute))))
|
||||
}
|
||||
|
||||
// Exercise item removal as well
|
||||
|
||||
@@ -23,4 +23,4 @@ limitations under the License.
|
||||
// * Multiple consumers and producers. In particular, it is allowed for an
|
||||
// item to be reenqueued while it is being processed.
|
||||
// * Shutdown notifications.
|
||||
package workqueue // import "k8s.io/client-go/util/workqueue"
|
||||
package workqueue
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 workqueue
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -87,6 +87,14 @@ type defaultQueueMetrics struct {
|
||||
// how long have current threads been working?
|
||||
unfinishedWorkSeconds SettableGaugeMetric
|
||||
longestRunningProcessor SettableGaugeMetric
|
||||
|
||||
// TODO(danielqsj): Remove the following metrics, they are deprecated
|
||||
deprecatedDepth GaugeMetric
|
||||
deprecatedAdds CounterMetric
|
||||
deprecatedLatency SummaryMetric
|
||||
deprecatedWorkDuration SummaryMetric
|
||||
deprecatedUnfinishedWorkSeconds SettableGaugeMetric
|
||||
deprecatedLongestRunningProcessor SettableGaugeMetric
|
||||
}
|
||||
|
||||
func (m *defaultQueueMetrics) add(item t) {
|
||||
@@ -95,7 +103,9 @@ func (m *defaultQueueMetrics) add(item t) {
|
||||
}
|
||||
|
||||
m.adds.Inc()
|
||||
m.deprecatedAdds.Inc()
|
||||
m.depth.Inc()
|
||||
m.deprecatedDepth.Inc()
|
||||
if _, exists := m.addTimes[item]; !exists {
|
||||
m.addTimes[item] = m.clock.Now()
|
||||
}
|
||||
@@ -107,9 +117,11 @@ func (m *defaultQueueMetrics) get(item t) {
|
||||
}
|
||||
|
||||
m.depth.Dec()
|
||||
m.deprecatedDepth.Dec()
|
||||
m.processingStartTimes[item] = m.clock.Now()
|
||||
if startTime, exists := m.addTimes[item]; exists {
|
||||
m.latency.Observe(m.sinceInSeconds(startTime))
|
||||
m.deprecatedLatency.Observe(m.sinceInMicroseconds(startTime))
|
||||
delete(m.addTimes, item)
|
||||
}
|
||||
}
|
||||
@@ -121,6 +133,7 @@ func (m *defaultQueueMetrics) done(item t) {
|
||||
|
||||
if startTime, exists := m.processingStartTimes[item]; exists {
|
||||
m.workDuration.Observe(m.sinceInSeconds(startTime))
|
||||
m.deprecatedWorkDuration.Observe(m.sinceInMicroseconds(startTime))
|
||||
delete(m.processingStartTimes, item)
|
||||
}
|
||||
}
|
||||
@@ -140,7 +153,9 @@ func (m *defaultQueueMetrics) updateUnfinishedWork() {
|
||||
// Convert to seconds; microseconds is unhelpfully granular for this.
|
||||
total /= 1000000
|
||||
m.unfinishedWorkSeconds.Set(total)
|
||||
m.deprecatedUnfinishedWorkSeconds.Set(total)
|
||||
m.longestRunningProcessor.Set(oldest / 1000000)
|
||||
m.deprecatedLongestRunningProcessor.Set(oldest) // in microseconds.
|
||||
}
|
||||
|
||||
type noMetrics struct{}
|
||||
@@ -185,6 +200,13 @@ type MetricsProvider interface {
|
||||
NewUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric
|
||||
NewLongestRunningProcessorSecondsMetric(name string) SettableGaugeMetric
|
||||
NewRetriesMetric(name string) CounterMetric
|
||||
NewDeprecatedDepthMetric(name string) GaugeMetric
|
||||
NewDeprecatedAddsMetric(name string) CounterMetric
|
||||
NewDeprecatedLatencyMetric(name string) SummaryMetric
|
||||
NewDeprecatedWorkDurationMetric(name string) SummaryMetric
|
||||
NewDeprecatedUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric
|
||||
NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric
|
||||
NewDeprecatedRetriesMetric(name string) CounterMetric
|
||||
}
|
||||
|
||||
type noopMetricsProvider struct{}
|
||||
@@ -217,6 +239,34 @@ func (_ noopMetricsProvider) NewRetriesMetric(name string) CounterMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedDepthMetric(name string) GaugeMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedAddsMetric(name string) CounterMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedLatencyMetric(name string) SummaryMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedWorkDurationMetric(name string) SummaryMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
func (_ noopMetricsProvider) NewDeprecatedRetriesMetric(name string) CounterMetric {
|
||||
return noopMetric{}
|
||||
}
|
||||
|
||||
var globalMetricsFactory = queueMetricsFactory{
|
||||
metricsProvider: noopMetricsProvider{},
|
||||
}
|
||||
@@ -239,15 +289,21 @@ func (f *queueMetricsFactory) newQueueMetrics(name string, clock clock.Clock) qu
|
||||
return noMetrics{}
|
||||
}
|
||||
return &defaultQueueMetrics{
|
||||
clock: clock,
|
||||
depth: mp.NewDepthMetric(name),
|
||||
adds: mp.NewAddsMetric(name),
|
||||
latency: mp.NewLatencyMetric(name),
|
||||
workDuration: mp.NewWorkDurationMetric(name),
|
||||
unfinishedWorkSeconds: mp.NewUnfinishedWorkSecondsMetric(name),
|
||||
longestRunningProcessor: mp.NewLongestRunningProcessorSecondsMetric(name),
|
||||
addTimes: map[t]time.Time{},
|
||||
processingStartTimes: map[t]time.Time{},
|
||||
clock: clock,
|
||||
depth: mp.NewDepthMetric(name),
|
||||
adds: mp.NewAddsMetric(name),
|
||||
latency: mp.NewLatencyMetric(name),
|
||||
workDuration: mp.NewWorkDurationMetric(name),
|
||||
unfinishedWorkSeconds: mp.NewUnfinishedWorkSecondsMetric(name),
|
||||
longestRunningProcessor: mp.NewLongestRunningProcessorSecondsMetric(name),
|
||||
deprecatedDepth: mp.NewDeprecatedDepthMetric(name),
|
||||
deprecatedAdds: mp.NewDeprecatedAddsMetric(name),
|
||||
deprecatedLatency: mp.NewDeprecatedLatencyMetric(name),
|
||||
deprecatedWorkDuration: mp.NewDeprecatedWorkDurationMetric(name),
|
||||
deprecatedUnfinishedWorkSeconds: mp.NewDeprecatedUnfinishedWorkSecondsMetric(name),
|
||||
deprecatedLongestRunningProcessor: mp.NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name),
|
||||
addTimes: map[t]time.Time{},
|
||||
processingStartTimes: map[t]time.Time{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -261,6 +317,16 @@ func newRetryMetrics(name string) retryMetrics {
|
||||
}
|
||||
}
|
||||
|
||||
func newDeprecatedRetryMetrics(name string) retryMetrics {
|
||||
var ret *defaultRetryMetrics
|
||||
if len(name) == 0 {
|
||||
return ret
|
||||
}
|
||||
return &defaultRetryMetrics{
|
||||
retries: globalMetricsFactory.metricsProvider.NewDeprecatedRetriesMetric(name),
|
||||
}
|
||||
}
|
||||
|
||||
// SetProvider sets the metrics provider for all subsequently created work
|
||||
// queues. Only the first call has an effect.
|
||||
func SetProvider(metricsProvider MetricsProvider) {
|
||||
|
||||
@@ -137,6 +137,14 @@ type testMetricsProvider struct {
|
||||
unfinished testMetric
|
||||
longest testMetric
|
||||
retries testMetric
|
||||
// deprecated metrics
|
||||
deprecatedDepth testMetric
|
||||
deprecatedAdds testMetric
|
||||
deprecatedLatency testMetric
|
||||
deprecatedDuration testMetric
|
||||
deprecatedUnfinished testMetric
|
||||
deprecatedLongest testMetric
|
||||
deprecatedRetries testMetric
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDepthMetric(name string) GaugeMetric {
|
||||
@@ -167,6 +175,34 @@ func (m *testMetricsProvider) NewRetriesMetric(name string) CounterMetric {
|
||||
return &m.retries
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedDepthMetric(name string) GaugeMetric {
|
||||
return &m.deprecatedDepth
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedAddsMetric(name string) CounterMetric {
|
||||
return &m.deprecatedAdds
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedLatencyMetric(name string) SummaryMetric {
|
||||
return &m.deprecatedLatency
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedWorkDurationMetric(name string) SummaryMetric {
|
||||
return &m.deprecatedDuration
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedUnfinishedWorkSecondsMetric(name string) SettableGaugeMetric {
|
||||
return &m.deprecatedUnfinished
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedLongestRunningProcessorMicrosecondsMetric(name string) SettableGaugeMetric {
|
||||
return &m.deprecatedLongest
|
||||
}
|
||||
|
||||
func (m *testMetricsProvider) NewDeprecatedRetriesMetric(name string) CounterMetric {
|
||||
return &m.deprecatedRetries
|
||||
}
|
||||
|
||||
func TestSinceInMicroseconds(t *testing.T) {
|
||||
mp := testMetricsProvider{}
|
||||
c := clock.NewFakeClock(time.Now())
|
||||
@@ -201,10 +237,18 @@ func TestMetrics(t *testing.T) {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := 1.0, mp.deprecatedAdds.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := 1.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
if e, a := 1.0, mp.deprecatedDepth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
c.Step(50 * time.Microsecond)
|
||||
|
||||
// Start processing
|
||||
@@ -219,6 +263,18 @@ func TestMetrics(t *testing.T) {
|
||||
if e, a := 1, mp.latency.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 50.0, mp.deprecatedLatency.observationValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1, mp.deprecatedLatency.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 0.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 0.0, mp.deprecatedDepth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// Add it back while processing; multiple adds of the same item are
|
||||
// de-duped.
|
||||
@@ -230,10 +286,16 @@ func TestMetrics(t *testing.T) {
|
||||
if e, a := 2.0, mp.adds.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 2.0, mp.deprecatedAdds.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
// One thing remains in the queue
|
||||
if e, a := 1.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1.0, mp.deprecatedDepth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
c.Step(25 * time.Microsecond)
|
||||
|
||||
@@ -246,11 +308,20 @@ func TestMetrics(t *testing.T) {
|
||||
if e, a := 1, mp.duration.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 25.0, mp.deprecatedDuration.observationValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1, mp.deprecatedDuration.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// One thing remains in the queue
|
||||
if e, a := 1.0, mp.depth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1.0, mp.deprecatedDepth.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// It should be back on the queue
|
||||
i, _ = q.Get()
|
||||
@@ -264,20 +335,35 @@ func TestMetrics(t *testing.T) {
|
||||
if e, a := 2, mp.latency.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 25.0, mp.deprecatedLatency.observationValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 2, mp.deprecatedLatency.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// use a channel to ensure we don't look at the metric before it's
|
||||
// been set.
|
||||
ch := make(chan struct{}, 1)
|
||||
mp.unfinished.notifyCh = ch
|
||||
mp.deprecatedUnfinished.notifyCh = ch
|
||||
c.Step(time.Millisecond)
|
||||
<-ch
|
||||
<-ch
|
||||
mp.unfinished.notifyCh = nil
|
||||
mp.deprecatedUnfinished.notifyCh = nil
|
||||
if e, a := .001, mp.unfinished.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := .001, mp.deprecatedUnfinished.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := .001, mp.longest.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1000.0, mp.deprecatedLongest.gaugeValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
|
||||
// Finish that one up
|
||||
q.Done(i)
|
||||
@@ -287,4 +373,10 @@ func TestMetrics(t *testing.T) {
|
||||
if e, a := 2, mp.duration.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 1000.0, mp.deprecatedDuration.observationValue(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
if e, a := 2, mp.deprecatedDuration.observationCount(); e != a {
|
||||
t.Errorf("expected %v, got %v", e, a)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,12 +28,13 @@ func TestRateLimitingQueue(t *testing.T) {
|
||||
queue := NewRateLimitingQueue(limiter).(*rateLimitingType)
|
||||
fakeClock := clock.NewFakeClock(time.Now())
|
||||
delayingQueue := &delayingType{
|
||||
Interface: New(),
|
||||
clock: fakeClock,
|
||||
heartbeat: fakeClock.NewTicker(maxWait),
|
||||
stopCh: make(chan struct{}),
|
||||
waitingForAddCh: make(chan *waitFor, 1000),
|
||||
metrics: newRetryMetrics(""),
|
||||
Interface: New(),
|
||||
clock: fakeClock,
|
||||
heartbeat: fakeClock.NewTicker(maxWait),
|
||||
stopCh: make(chan struct{}),
|
||||
waitingForAddCh: make(chan *waitFor, 1000),
|
||||
metrics: newRetryMetrics(""),
|
||||
deprecatedMetrics: newDeprecatedRetryMetrics(""),
|
||||
}
|
||||
queue.DelayingInterface = delayingQueue
|
||||
|
||||
|
||||
Reference in New Issue
Block a user