Compare commits

...

69 Commits

Author SHA1 Message Date
Kubernetes Publisher
46b5520a87 Fix Godeps.json to point to kubernetes-1.11.0-beta.1 tags 2018-06-08 15:32:32 +00:00
Kubernetes Publisher
599e5c2d9a Merge remote-tracking branch 'origin/master' into release-1.11
Kubernetes-commit: 4e3b2843df571c3b80c834d7c23bc6da1a22aab8
2018-05-31 14:24:28 -04:00
Kubernetes Publisher
54553fda9f Merge pull request #61803 from awly/client-auth-exec-tls
Automatic merge from submit-queue (batch tested with PRs 61803, 64305, 64170, 64361, 64339). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Add TLS support to exec authenticator plugin

**What this PR does / why we need it**:
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/auth/kubectl-exec-plugins.md#tls-client-certificate-support

Allows exec plugin to return raw TLS key/cert data. This data populates
transport.Config.TLS field.
This requires a change to AuthProvider interface to expose TLS configs,
not only RoundTripper.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #61421

**Special notes for your reviewer**:

**Release note**:

```release-note
Exec authenticator plugin supports TLS client certificates.
```

Kubernetes-commit: f701b7529937493a64f2f2553aa9a5cd7020d9b7
2018-06-08 15:31:01 +00:00
Kubernetes Publisher
b9e2054501 Merge pull request #62306 from freehan/pod-status-patch2
Automatic merge from submit-queue (batch tested with PRs 58920, 58327, 60577, 49388, 62306). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Use Patch instead of Put to sync pod status

ref: https://github.com/kubernetes/community/blob/master/keps/sig-network/0007-pod-ready%2B%2B.md
```release-note
Use Patch instead of Put to sync pod status
```

Kubernetes-commit: ea92879fab9eb9cd7a2529101fb088c2f07bd547
2018-06-08 15:31:00 +00:00
Kubernetes Publisher
0f896184a7 Merge pull request #60577 from timchenxiaoyu/fixpersist
Automatic merge from submit-queue (batch tested with PRs 58920, 58327, 60577, 49388, 62306). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

fix persist typo

I wonder this pr should pull to kubernetes/kubernetes  or  kubernetes/client-go ?

```
NONE
```

Kubernetes-commit: 5cf652d899d464a63a99aceaab9cf9276294b602
2018-06-08 15:30:59 +00:00
Kubernetes Publisher
26ba46adf7 Merge pull request #64213 from dashpole/eviction_event_annotation
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Add metadata to kubelet eviction event annotations

**What this PR does / why we need it**:
Add annotations to kubelet eviction events.  Annotations include
"offending_containers" : comma-seperated list of containers.
"offending_containers_usage": comma-seperated list of usage.
"starved_resource": v1.ResourceName of the starved resource

**Special notes for your reviewer**:
Adding annotations to events required changing the `EventRecorder` interface to add a `AnnotatedEventf` function, which can add annotations to an event.

**Release note**:
```release-note
NONE
```
/assign @dchen1107
cc @mwielgus @schylek @kgrygiel

Kubernetes-commit: 15cd3552819367aef63114dcf7fa87b216d5dc62
2018-06-08 15:30:59 +00:00
Kubernetes Publisher
966db4b3a2 Merge pull request #64314 from sttts/sttts-start-fresh-client-go-owners
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

client-go: start fresh with owner file

After client-go's OWNER file has grown to 50ish many reviewers, It's time to start fresh and re-add those who really want to review. Please don't be shy to come forward if you want to stay on that list. I will re-add you.

Kubernetes-commit: 10b9fd3a01f37b9a6f1ce636edcbd9c7332414cd
2018-06-08 15:30:58 +00:00
Kubernetes Publisher
3fe7061dad Merge pull request #63893 from jennybuckley/expose-openapi-to-registry3
Automatic merge from submit-queue (batch tested with PRs 64175, 63893). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Expose openapi schema to handlers

**What this PR does / why we need it**:
Build an openapi spec for each api resource handler. This spec will be able to be consumed by server-side apply and server-side openapi validation.
The reason for putting it into master is so we can work on implementing server side validation against the openapi spec as well as server side apply, and it will make merging the server side apply feature branch a smaller, less risky PR

/sig api-machinery
/kind feature
cc @liggitt @lavalamp @seans3 @mbohlool @apelisse

**Release note**:
```release-note
NONE
```

Kubernetes-commit: 28f171bd66937dec8b24a05c4b7a1414432f9fe8
2018-06-08 15:30:57 +00:00
Andrew Lytvynov
0684545aa5 Add TLS support to exec authenticator plugin
https://github.com/kubernetes/community/blob/master/contributors/design-proposals/auth/kubectl-exec-plugins.md#tls-client-certificate-support

Allows exec plugin to return raw TLS key/cert data. This data populates
transport.Config.TLS fields.
transport.Config.TLS propagates custom credentials using
tls.Config.GetClientCertificate callback.
On key/cert rotation, all connections using old credentials are
closed

Kubernetes-commit: cd89f9473faa60c15b8e9d223e5c4f9dab53627a
2018-05-30 14:03:32 -07:00
Dr. Stefan Schimanski
517bcf1469 client-go: start fresh with owner file
Kubernetes-commit: 11f65b2a30be2bfc014c563dc7a8e98ec3ccc1ff
2018-05-25 15:49:44 +02:00
Dr. Stefan Schimanski
b66a02842a client-go: document README exception in .github/PULL_REQUEST_TEMPLATE.md
Kubernetes-commit: f6d4244c30060bcf6ebe4ad80ecec47e836aca30
2018-05-29 09:16:25 +02:00
jennybuckley
9ca66310eb Run hack/update-all.sh
Kubernetes-commit: 349fbdfe9fbcad91fcecbfe4e71fa91d235dad6d
2018-05-24 09:55:33 -07:00
David Ashpole
c3d9963cb5 add metadata to kubelet eviction event annotations
Kubernetes-commit: fd1f19fc423880b2b292d6f9e6fca1e941e87994
2018-05-23 16:12:54 -07:00
David Eads
6a96aaddc7 prevent zero for leader election timeouts
Kubernetes-commit: 7288e8828f5bf659d41e71760f9d9923e405e2e4
2018-05-23 15:00:37 -04:00
Kubernetes Publisher
be44d9f407 Merge remote-tracking branch 'origin/master' into release-1.11. Deleting CHANGELOG-1.10.md
Kubernetes-commit: 513e080e6a665c4ae03911c7674eed34edff4519
2018-05-21 15:35:20 -04:00
Kubernetes Publisher
d1038de14e Merge pull request #60464 from roycaihw/loadconfig
Automatic merge from submit-queue (batch tested with PRs 63598, 63913, 63459, 63963, 60464). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Client-go raises error on duplicated name in kubeconfig

(for NamedCluster, NamedContext, NamedUser, NamedExtension)

**What this PR does / why we need it**:
Client should detect duplicated name when loading `name-value` based lists in kubeconfig: `users`, `clusters`, `contexts`. Currently if there are multiple value with same name, `client-python` will pick the first one, while `client-go` will pick the last.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
ref: kubernetes-client/python#445, kubernetes-client/python-base#47

**Special notes for your reviewer**:

**Release note**:

```release-note
kubectl and client-go now detects duplicated name for user, cluster and context when loading kubeconfig and reports error
```

/sig api-machinery

cc @brendandburns @mbohlool

Kubernetes-commit: 7909712ca574c536901bc7858dfbf72a3a6ee7dd
2018-06-08 15:30:30 +00:00
Kubernetes Publisher
7b33f1b070 Merge pull request #63913 from deads2k/controller-10-event
Automatic merge from submit-queue (batch tested with PRs 63598, 63913, 63459, 63963, 60464). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

fix event ref determination for apigroups

The event ref determination was never updated to handle apigroups so it has been returning only a group (not a version).

@kubernetes/sig-apps-bugs

```release-note
event object references with apiversion will now report an apiversion.
```

Kubernetes-commit: 4810b9ba679f4fb9cc39f3a83bbcd23b3e4accce
2018-06-08 15:30:30 +00:00
Kubernetes Publisher
9405a468ab Merge remote-tracking branch 'origin/master' into release-1.11
Kubernetes-commit: 57566f26f8e426b26b46c59ee698ebd85f4de29f
2018-06-08 15:30:29 +00:00
Kubernetes Publisher
ea16f6128e Merge pull request #63875 from deads2k/client-10-timeout
Automatic merge from submit-queue (batch tested with PRs 63875, 63817). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

make TestGetServerGroupsWithTimeout more reliable

Stops overriding a global variable in a test and tolerates a different kind of timeout message you can see.

/assign @soltysh

Kubernetes-commit: baad3d4159db43927e250d4b3f23d6e083b01294
2018-05-16 18:32:14 +00:00
Andrew Lytvynov
6c082e8151 Extract connection rotating dialer into a package
This will be re-used for exec auth plugin to rotate connections on
credential change.

Kubernetes-commit: 85a61ff3aa7df8d83af304ebffab780fabd028a8
2018-05-16 10:30:53 -07:00
David Eads
8417b79cae fix event ref determination for apigroups
Kubernetes-commit: b2be8953b147d4c386768b0bdd3d9a93a47a625b
2018-05-16 08:08:20 -04:00
Mikhail Mazurskiy
603d97a703 Use Dial with context
Kubernetes-commit: 5e8e570dbda6ed89af9bc2e0a05e3d94bfdfcb61
2018-05-19 08:14:37 +10:00
Kubernetes Publisher
79540301d5 Merge pull request #63861 from deads2k/client-09-clean
Automatic merge from submit-queue (batch tested with PRs 63589, 63644, 63861, 63872, 63847). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

remove service.deletecollection since the server doesn't support it

Updates the generated service client to match the API available.

@kubernetes/sig-api-machinery-pr-reviews
@kubernetes/api-reviewers

```release-note
NONE
```

Kubernetes-commit: 49e9322d4f62cda83e3eac815e202967dc1a0333
2018-05-16 02:29:53 +00:00
Kubernetes Publisher
f9b6f71f0a Merge pull request #63800 from wojtek-t/fix_fake_listers
Automatic merge from submit-queue (batch tested with PRs 63658, 63509, 63800, 63586, 63840). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Fix List in fake clients to propagate ListMeta

Kubernetes-commit: 765c49db41dbe067cfca5d83cf438fb02b3468b8
2018-05-15 14:23:16 -07:00
Kubernetes Publisher
690cda5361 Merge pull request #63550 from juanvallejo/jvallejo/move-cached-discovery
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

move cached_discovery to client-go/discovery

**Release note**:
```release-note
NONE
```

Moves the cmd/util CachedDiscoveryClient to client-go

cc @soltysh @deads2k

Kubernetes-commit: f2ea83bef88f9d2783abe0c00de563db13ec04f4
2018-05-15 18:30:59 +00:00
David Eads
ef648e2917 make TestGetServerGroupsWithTimeout more reliable
Kubernetes-commit: e7620e814aebca184160f2ae5ef243f5dcd1f409
2018-05-15 12:47:23 -04:00
David Eads
10b605faab generated
Kubernetes-commit: eb438b088ccf2800e58c37aa8aefe6ce6482aacb
2018-05-15 09:00:50 -04:00
Kubernetes Publisher
988feb35af Merge pull request #63100 from ravisantoshgudimetla/priority-beta-api
Automatic merge from submit-queue (batch tested with PRs 55511, 63372, 63400, 63100, 63769). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Create pkg/scheduling/apis/v1beta1 and move priorityClass to beta

**What this PR does / why we need it**:
This is for creating pkg/apis/scheduling/v1beta1 so that priorityClasses could be moved to beta.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Part of #57471

**Special notes for your reviewer**:
/cc @bsalamat @aveshagarwal

**Release note**:

```release-note
The `PriorityClass` API is promoted to `scheduling.k8s.io/v1beta1`
```

Kubernetes-commit: a1b54f3c99f2ae4d7d10c269939e5c0bb6d03e6f
2018-05-14 22:30:03 +00:00
wojtekt
41a5bc501f Autogenerated code
Kubernetes-commit: c69165d50386d12c8644bd6de974a9d2fdfc876c
2018-05-14 16:14:53 +02:00
Kubernetes Publisher
421cf66e41 Merge pull request #63446 from deads2k/client-08-remove-old
Automatic merge from submit-queue (batch tested with PRs 63367, 63718, 63446, 63723, 63720). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

finish new dynamic client and deprecate old dynamic client

Builds on a couple other pulls.  This completes the transition to the new dynamic client.

@kubernetes/sig-api-machinery-pr-reviews 
@caesarxuchao @sttts 

```release-note
The old dynamic client has been replaced by a new one.  The previous dynamic client will exist for one release in `client-go/deprecated-dynamic`.  Switch as soon as possible.
```

Kubernetes-commit: 92ba95c39c6f7192502c3d907006c8828dd7b32c
2018-05-11 14:49:16 -07:00
juanvallejo
a0e8687452 restore old cached client behavior
Kubernetes-commit: 57f308ae60875e90004dca592d47cbf6bce390ba
2018-05-11 15:50:13 -04:00
Kubernetes Publisher
b4efb2d46b Merge pull request #59727 from wgliang/master.time
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

should use time.Since instead of time.Now().Sub

**What this PR does / why we need it**:
should use time.Since instead of time.Now().Sub

**Special notes for your reviewer**:

Kubernetes-commit: 7eb88f11d23d2be7dc3a91f727a1a77a0abac5e8
2018-05-11 14:29:34 +00:00
Kubernetes Publisher
cf2db96347 Merge pull request #63613 from deads2k/cli-52-builderclient
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

 construct resource.Builder from kubeconfig flags

updates the resource.Builder to be constructed from the kubeconfig flags struct/interface that we now have.

@kubernetes/sig-cli-maintainers
@juanvallejo @soltysh

```release-note
NONE
```

Kubernetes-commit: 7e75a09db6dc13218b4f5e06493115ae96f83774
2018-05-10 18:29:26 +00:00
Kubernetes Publisher
b2243688f8 Merge pull request #60200 from dixudx/clientgo_openstack_config
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

read openstack auth config from client config

**What this PR does / why we need it**:
> // TODO: read/persist client configuration(OS_XXX env vars) in config

/sig openstack

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #

**Special notes for your reviewer**:
/assign @dims
**Release note**:

```release-note
read openstack auth config from client config
```

Kubernetes-commit: 9dcbdc3d459ec6b2bb149a9f4f3c0d1348113e4a
2018-05-10 18:29:03 +00:00
Kubernetes Publisher
638bb430f4 Merge pull request #61976 from atlassian/ticker-with-stop
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Stop() for Ticker to enable leak-free code

**What this PR does / why we need it**:
I wanted to use the clock package but the `Ticker` without a `Stop()` method is a deal breaker for me.

**Release note**:
```release-note
NONE
```
/kind enhancement
/sig api-machinery

Kubernetes-commit: d42df4561a6c754120e9b46b37c032a57ca92a9a
2018-05-10 06:27:21 +00:00
Kubernetes Publisher
9cabba1998 Merge pull request #63602 from deads2k/cli-54-categories
Automatic merge from submit-queue (batch tested with PRs 59284, 63602). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

 category expansion can only come from the server

A couple release ago we moved category expansion to the server instead of hardcoding it in the client.  Similar to restmappings, there is no valid client-side expansion anymore, so this removes the code that hardcoded the list and moves the category expansion to the same package as our discovery based restmappers.

@kubernetes/sig-cli-maintainers

```release-note
NONE
```

Kubernetes-commit: ca92b73a659bf92c3051765a6ea5bc8c12069975
2018-05-09 22:27:11 +00:00
Kubernetes Publisher
de3c9b6cf8 Merge pull request #63502 from liggitt/parallel-discovery
Automatic merge from submit-queue (batch tested with PRs 62354, 62934, 63502). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Run resource discovery in parallel

best viewed ignoring whitespace (https://github.com/kubernetes/kubernetes/pull/63502/files?w=1)

on high-latency connections, serializing resource discovery requests across group versions can take significant amounts of time. this parallelizes the network request portion of the discovery call

xref #63368

```release-note
NONE
```

Kubernetes-commit: 234939dced42952045fc2a42b74a805affcff965
2018-05-09 18:27:48 +00:00
Kubernetes Publisher
62c4633c17 Merge pull request #63565 from roycaihw/bump-kube-openapi-dep
Automatic merge from submit-queue (batch tested with PRs 59034, 63565, 63533). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Bump kube-openapi dependency

picks: https://github.com/kubernetes/kube-openapi/pull/67
ref: https://github.com/kubernetes/kubernetes/issues/63494

**Release note**:

```release-note
NONE
```

Kubernetes-commit: 3663dc757e05fb79f23a14ad4f2ba832d6e5962c
2018-05-09 18:27:28 +00:00
David Eads
3fb1070233 construct resource.Builder from kubeconfig flags
Kubernetes-commit: 1f5357034b4a8ef4ed68f0c2415e280601968e91
2018-05-09 13:53:07 -04:00
David Eads
f6af22edb3 fix dynamic client name
Kubernetes-commit: fd044d152ee13a6cb812e4c3e7504ee8e24b5b8c
2018-05-09 12:58:12 -04:00
David Eads
1c46f3b96c move old dynamic client to deprecated-client
Kubernetes-commit: d8924bc1c914c63fd7e93f7e562edfddd911d9d7
2018-05-09 12:54:24 -04:00
David Eads
77541e5cb7 add subresource support for the dynamic client
Kubernetes-commit: 82e32d2a3260807237a69bc40fb371db640d26fc
2018-05-09 12:52:12 -04:00
ravisantoshgudimetla
d50d58e11c Generated
Kubernetes-commit: f20bd00ab279ad4ac6e887007c5dad6bbc4b3bb9
2018-05-09 11:17:18 -04:00
David Eads
37c8d52754 category expansion can only come from the server
Kubernetes-commit: ad87219b2cba1d22ac2a808568da7322775972ae
2018-05-09 11:12:32 -04:00
David Eads
0c30aacc9d move category expansion types to restmapper package
Kubernetes-commit: 37f6cb723017edb46117d64d70c827a2d8c93b59
2018-05-09 11:01:49 -04:00
Kubernetes Publisher
9124a4f71a Merge pull request #63364 from deads2k/api-16-scheme
Automatic merge from submit-queue (batch tested with PRs 63364, 63464). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

simplify api registration

The current registration and groupmeta is only use to determine a preferred ordering to versions.  The scheme already knows about all versions, so this simply makes that knowledge official.  After doing that, the announce, registered, and apimachinery/pkg/apimachinery all drop out.

With this change we'll be able to create `install` packages for each external apigroup that accept a scheme and have suggested orderings.  This will make it possible to close the consistency gap with kubectl, client, and apiserver.

@kubernetes/sig-api-machinery-pr-reviews
@lavalamp @smarterclayton @liggitt @sttts

```release-note
NONE
```

Kubernetes-commit: f929502282b370ceb3adae4816074142d6702c8b
2018-05-09 02:27:12 +00:00
Kubernetes Publisher
c7b9128fb6 Merge pull request #63507 from deads2k/cli-50-tidyup
Automatic merge from submit-queue (batch tested with PRs 63291, 63490, 60445, 63507, 63524). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

 move client based restmappers to client-go

Moves the client-based restmappers to client-go where everyone who needs them can have access.

```release-note
the shortcuts which were moved server-side in at least 1.9 have been removed from being hardcoded in kubectl
```

@kubernetes/sig-cli-maintainers @kubernetes/sig-api-machinery-pr-reviews

Kubernetes-commit: c27335fe3e75ef3d680dc5f470b16764564dc3b5
2018-05-09 02:26:50 +00:00
Kubernetes Publisher
e06cc6501b Merge pull request #60445 from oracle/for/upstream/master/60444
Automatic merge from submit-queue (batch tested with PRs 63291, 63490, 60445, 63507, 63524). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Fixes fake client generation for non-namespaced subresources

**What this PR does / why we need it**:

Fixes code generation for non-namespaced subresources fake clients.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #60444

**Special notes for your reviewer**:

**Release note**:

```dev-release-note
Fixes fake client generation for non-namespaced subresources
```

/cc @mfojtik @liggitt

I'm not sure the best way to add tests for this. Any pointers?

Kubernetes-commit: 8203d35ea830b02a542c3099e302d58344a86305
2018-05-09 02:26:50 +00:00
Haowei Cai
7a2dcd71b0 generated
Kubernetes-commit: 18fd392c1358fccdac0905e29ae957b2ddcd213a
2018-05-08 17:27:17 -07:00
juanvallejo
8a7f1bb868 move cached_discovery to client-go/discovery
Kubernetes-commit: 405935574307d460124f30df06860dc670aa634c
2018-05-08 13:50:36 -04:00
Jordan Liggitt
334b50415a Run resource discovery in parallel
Kubernetes-commit: d037b0893fa9313b9b5b111c22d49bf3c859a9d1
2018-05-07 15:54:25 -04:00
David Eads
1c9ae1b2ac move client based restmappers to client-go
Kubernetes-commit: dd97a7bc59c913c71730dba8b8de274820466417
2018-05-07 15:41:13 -04:00
Kubernetes Publisher
8296aa1708 Merge pull request #61154 from hanxiaoshuai/bugfix0314
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

catch err when Watch testResource failed in func TestWatchCallNonNamespace

**What this PR does / why we need it**:
catch err when Watch testResource failed in func TestWatchCallNonNamespace
**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #
[#61155](https://github.com/kubernetes/kubernetes/issues/61155)
**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```

Kubernetes-commit: 89542d9ec97febf16d14319002d1b164a823bb8b
2018-05-07 14:28:00 +00:00
David Eads
6174473dce simplify api registration
Kubernetes-commit: c5445d3c56e06ab366b9cca34bd69c5cc386ec47
2018-05-07 08:32:20 -04:00
David Eads
5c71aff0f3 generated
Kubernetes-commit: 7b4f97aca3f47aed1161a20636a1a078a63c9fd9
2018-05-07 08:32:03 -04:00
Kubernetes Publisher
bf62f5b7d6 Merge pull request #63421 from liggitt/discover-completions
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Cache preferred resources, use in kubectl resource name autocomplete

Fixes #63145
Fixes https://github.com/kubernetes/kubectl/issues/357
Alternative to #61928

* starts to unify preferred resource logic on top of ServerGroups()/ServerResourcesForGroupVersion() methods
* allows indicating a cached list of resources is acceptable when calling `kubectl api-resources` (default is still to rediscover)
* uses `kubectl api-resources` in bash completion

```sh
$ kubectl get [TAB][TAB]
apiservices.apiregistration.k8s.io                            networkpolicies.extensions
certificatesigningrequests.certificates.k8s.io                networkpolicies.networking.k8s.io
clusterrolebindings.rbac.authorization.k8s.io                 nodes
clusterroles.rbac.authorization.k8s.io                        persistentvolumeclaims
componentstatuses                                             persistentvolumes
configmaps                                                    poddisruptionbudgets.policy
controllerrevisions.apps                                      pods
cronjobs.batch                                                podsecuritypolicies.extensions
customresourcedefinitions.apiextensions.k8s.io                podsecuritypolicies.policy
daemonsets.apps                                               podtemplates
daemonsets.extensions                                         replicasets.apps
deployments.apps                                              replicasets.extensions
deployments.extensions                                        replicationcontrollers
endpoints                                                     resourcequotas
events                                                        rolebindings.rbac.authorization.k8s.io
events.events.k8s.io                                          roles.rbac.authorization.k8s.io
horizontalpodautoscalers.autoscaling                          secrets
ingresses.extensions                                          serviceaccounts
initializerconfigurations.admissionregistration.k8s.io        services
jobs.batch                                                    statefulsets.apps
limitranges                                                   storageclasses.storage.k8s.io
mutatingwebhookconfigurations.admissionregistration.k8s.io    validatingwebhookconfigurations.admissionregistration.k8s.io
namespaces                                                    volumeattachments.storage.k8s.io
```

```release-note
NONE
```

Kubernetes-commit: 068b7befa926d376634c79cbba3d210c1dc596fe
2018-05-04 18:28:09 +00:00
Kubernetes Publisher
998a5ff4b9 Merge pull request #63405 from dims/update-to-latest-gophercloud-may-3-2018
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Update to latest Gophercloud

**What this PR does / why we need it**:

periodic update to latest gophercloud. The changes are as follows:
6da026c32e...781450b3c4

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```

Kubernetes-commit: bc56947e8dd89d70735384239c4e5d0c2c9fe8eb
2018-05-04 18:27:44 +00:00
Jordan Liggitt
46ab86af26 Make ServerPreferred[Namespaced]Resources logic and caches consistent
Kubernetes-commit: 74b7cec0c6b1355615097be4068500761a9893fd
2018-05-03 23:34:09 -04:00
Kubernetes Publisher
7e5a9c2cb4 Merge pull request #63346 from roycaihw/bump-kube-openapi
Automatic merge from submit-queue (batch tested with PRs 61455, 63346, 63130, 63404). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

Bump kube-openapi dependency

**What this PR does / why we need it**:
Pick up https://github.com/kubernetes/kube-openapi/pull/64

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #63218

**Special notes for your reviewer**:

**Release note**:

```release-note
NONE
```

/sig api-machinery
/cc @mbohlool @liggitt

Kubernetes-commit: 89e6895e1c550658b7c145436868b70fb3cabbcd
2018-05-04 02:27:28 +00:00
Davanum Srinivas
d17062c637 Update to latest Gophercloud
6da026c32e...781450b3c4

Kubernetes-commit: ddfcf1e193b573db17097e88201d717ac9ac1630
2018-05-03 15:47:58 -04:00
Haowei Cai
835de9289c Bump kube-openapi dependency
Kubernetes-commit: 212814a0c6625d9359afbdbfa50f8e187e59fc0e
2018-05-01 17:33:27 -07:00
Minhan Xia
a53e5845b9 add Patch support in fake kubeClient
Kubernetes-commit: 8b3b4e4deabe4cf922eee752df2fad189b2c1471
2018-04-11 11:37:30 -07:00
Mikhail Mazurskiy
9446f4ef9d Stop() for Ticker to enable leak-free code
Kubernetes-commit: 1f393cdef96fe6e4ddcbf93825d65a9980463406
2018-03-31 19:41:43 +11:00
hangaoshuai
e39ef65572 catch err when Watch testResource failed in func TestWatchCallNonNamespace
Kubernetes-commit: c63e22eea56c2ba3c24a284505fbe869b7678e14
2018-03-20 16:35:41 +08:00
root
4bc82dd2a3 fix persist typo
Kubernetes-commit: 284d08bf7032a94b568a95d6de1e13d8c0ac5bc2
2018-02-28 19:11:35 +08:00
Haowei Cai
5f9a755f73 Raise error on duplicate name in kubeconfig
for NamedCluster, NamedContext, NamedUser, NamedExtension

Kubernetes-commit: e9454a383b52c3909e7bb73a0263c4d2c0c2c2db
2018-02-26 15:58:33 -08:00
Josh Horwitz
64101cbe6a Fixes fake client generation for non-namespaced subresources
Kubernetes-commit: 0f62a8cddac0a48506fc1b93f37da32530fd2358
2018-02-26 14:03:11 -05:00
Di Xu
a258223ae4 read openstack auth config from client config
Kubernetes-commit: 10201f3f2ae1841cb1a68ea420c94bf018ae6b24
2018-02-22 18:05:24 +08:00
Wang Guoliang
d90294e8f9 should use time.Since instead of time.Now().Sub
Kubernetes-commit: 89669283fe84619f0c15af8495ccb28a752bb1e8
2018-02-11 21:17:00 +08:00
891 changed files with 4645 additions and 275779 deletions

View File

@@ -1,2 +1,3 @@
Sorry, we do not accept changes directly against this repository. Please see
CONTRIBUTING.md for information on where and how to contribute instead.
Sorry, we do not accept changes directly against this repository, unless the
change is to the `README.md` itself. Please see
`CONTRIBUTING.md` for information on where and how to contribute instead.

208
Godeps/Godeps.json generated
View File

@@ -1,6 +1,6 @@
{
"ImportPath": "k8s.io/client-go",
"GoVersion": "go1.9",
"GoVersion": "go1.10",
"GodepVersion": "v80",
"Packages": [
"./..."
@@ -86,6 +86,10 @@
"ImportPath": "github.com/golang/protobuf/ptypes/timestamp",
"Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9"
},
{
"ImportPath": "github.com/google/btree",
"Rev": "7d79101e329e5a3adf994758c578dab82b90c017"
},
{
"ImportPath": "github.com/google/gofuzz",
"Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c"
@@ -104,31 +108,39 @@
},
{
"ImportPath": "github.com/gophercloud/gophercloud",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/openstack/utils",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gophercloud/gophercloud/pagination",
"Rev": "6da026c32e2d622cc242d32984259c77237aefe1"
"Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d"
},
{
"ImportPath": "github.com/gregjones/httpcache",
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
},
{
"ImportPath": "github.com/gregjones/httpcache/diskcache",
"Rev": "787624de3eb7bd915c329cba748687a3b22666a6"
},
{
"ImportPath": "github.com/hashicorp/golang-lru",
@@ -154,6 +166,10 @@
"ImportPath": "github.com/modern-go/reflect2",
"Rev": "05fbef0ca5da472bbf96c9322b84a53edc03c9fd"
},
{
"ImportPath": "github.com/peterbourgon/diskv",
"Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6"
},
{
"ImportPath": "github.com/pmezard/go-difflib/difflib",
"Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d"
@@ -252,335 +268,327 @@
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/apps/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/apps/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/apps/v1beta2",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/authentication/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/authentication/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/authorization/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/authorization/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/autoscaling/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/autoscaling/v2beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/batch/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/batch/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/batch/v2alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/certificates/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/core/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/events/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/extensions/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/imagepolicy/v1alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/networking/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/policy/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/rbac/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/rbac/v1alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/rbac/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/scheduling/v1alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/scheduling/v1beta1",
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/settings/v1alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/storage/v1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/storage/v1alpha1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/api/storage/v1beta1",
"Rev": "b7d77fa220f5130ec63c2ca7167dd9653449c64d"
"Rev": "c71adde6150917c4e19dfef555f427d5e085f05d"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery/announced",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apimachinery/registered",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/version",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "b54e2be8c5c22805a615d4e84c3cbffcdca8654f"
"Rev": "40bc35ef007c446a3ed3d1a2d51ed2d9f30f55f4"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",
"Rev": "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
"Rev": "86e28c192d2743f0232b9bc5f0a531568ef9f2a5"
}
]
}

40
OWNERS
View File

@@ -1,45 +1,15 @@
approvers:
- caesarxuchao
- deads2k
- krousey
- lavalamp
- liggitt
- smarterclayton
- sttts
- liggitt
reviewers:
- thockin
- lavalamp
- smarterclayton
- wojtek-t
- deads2k
- yujuhong
- derekwaynecarr
- caesarxuchao
- vishh
- mikedanese
- deads2k
- lavalamp
- liggitt
- nikhiljindal
- gmarek
- erictune
- davidopp
- pmorie
- sttts
- dchen1107
- saad-ali
- zmerlynn
- luxas
- janetkuo
- justinsb
- roberthbailey
- ncdc
- tallclair
- yifan-gu
- eparis
- mwielgus
- timothysc
- feiskyer
- jlowdermilk
- soltysh
- piosz
- jsafrane
- awly
- sttts
- yliaog

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package dynamic
package deprecated_dynamic
import (
"encoding/json"

View File

@@ -17,7 +17,7 @@ limitations under the License.
// Package dynamic provides a client interface to arbitrary Kubernetes
// APIs that exposes common high level operations and exposes common
// metadata.
package dynamic
package deprecated_dynamic
import (
"strings"
@@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
restclient "k8s.io/client-go/rest"
)
@@ -65,13 +66,13 @@ type ResourceInterface interface {
// and manipulate metadata of a Kubernetes API group, and implements Interface.
type Client struct {
version schema.GroupVersion
delegate DynamicInterface
delegate dynamic.Interface
}
// NewClient returns a new client based on the passed in config. The
// codec is ignored, as the dynamic client uses it's own codec.
func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, error) {
delegate, err := NewForConfig(conf)
delegate, err := dynamic.NewForConfig(conf)
if err != nil {
return nil, err
}
@@ -84,30 +85,47 @@ func NewClient(conf *restclient.Config, version schema.GroupVersion) (*Client, e
// is ignored. The ResourceInterface inherits the parameter codec of c.
func (c *Client) Resource(resource *metav1.APIResource, namespace string) ResourceInterface {
resourceTokens := strings.SplitN(resource.Name, "/", 2)
subresource := ""
subresources := []string{}
if len(resourceTokens) > 1 {
subresource = resourceTokens[1]
subresources = strings.Split(resourceTokens[1], "/")
}
if len(namespace) == 0 {
return oldResourceShim(c.delegate.ClusterSubresource(c.version.WithResource(resourceTokens[0]), subresource))
return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])), subresources)
}
return oldResourceShim(c.delegate.NamespacedSubresource(c.version.WithResource(resourceTokens[0]), subresource, namespace))
return oldResourceShim(c.delegate.Resource(c.version.WithResource(resourceTokens[0])).Namespace(namespace), subresources)
}
// the old interfaces used the wrong type for lists. this fixes that
func oldResourceShim(in DynamicResourceInterface) ResourceInterface {
return oldResourceShimType{DynamicResourceInterface: in}
func oldResourceShim(in dynamic.ResourceInterface, subresources []string) ResourceInterface {
return oldResourceShimType{ResourceInterface: in, subresources: subresources}
}
type oldResourceShimType struct {
DynamicResourceInterface
dynamic.ResourceInterface
subresources []string
}
func (s oldResourceShimType) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Create(obj, s.subresources...)
}
func (s oldResourceShimType) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Update(obj, s.subresources...)
}
func (s oldResourceShimType) Delete(name string, opts *metav1.DeleteOptions) error {
return s.ResourceInterface.Delete(name, opts, s.subresources...)
}
func (s oldResourceShimType) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
return s.ResourceInterface.Get(name, opts, s.subresources...)
}
func (s oldResourceShimType) List(opts metav1.ListOptions) (runtime.Object, error) {
return s.DynamicResourceInterface.List(opts)
return s.ResourceInterface.List(opts)
}
func (s oldResourceShimType) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
return s.DynamicResourceInterface.Patch(name, pt, data)
return s.ResourceInterface.Patch(name, pt, data, s.subresources...)
}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package dynamic
package deprecated_dynamic
import (
"sync"

View File

@@ -0,0 +1,623 @@
/*
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 deprecated_dynamic
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"reflect"
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
restclient "k8s.io/client-go/rest"
restclientwatch "k8s.io/client-go/rest/watch"
)
func getJSON(version, kind, name string) []byte {
return []byte(fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "metadata": {"name": %q}}`, version, kind, name))
}
func getListJSON(version, kind string, items ...[]byte) []byte {
json := fmt.Sprintf(`{"apiVersion": %q, "kind": %q, "items": [%s]}`,
version, kind, bytes.Join(items, []byte(",")))
return []byte(json)
}
func getObject(version, kind, name string) *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": version,
"kind": kind,
"metadata": map[string]interface{}{
"name": name,
},
},
}
}
func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) {
srv := httptest.NewServer(http.HandlerFunc(h))
cl, err := NewClient(&restclient.Config{
Host: srv.URL,
ContentConfig: restclient.ContentConfig{GroupVersion: gv},
}, *gv)
if err != nil {
srv.Close()
return nil, nil, err
}
return cl, srv, nil
}
func TestList(t *testing.T) {
tcs := []struct {
name string
namespace string
path string
resp []byte
want *unstructured.UnstructuredList
}{
{
name: "normal_list",
path: "/apis/gtest/vtest/rtest",
resp: getListJSON("vTest", "rTestList",
getJSON("vTest", "rTest", "item1"),
getJSON("vTest", "rTest", "item2")),
want: &unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "vTest",
"kind": "rTestList",
},
Items: []unstructured.Unstructured{
*getObject("vTest", "rTest", "item1"),
*getObject("vTest", "rTest", "item2"),
},
},
},
{
name: "namespaced_list",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
resp: getListJSON("vTest", "rTestList",
getJSON("vTest", "rTest", "item1"),
getJSON("vTest", "rTest", "item2")),
want: &unstructured.UnstructuredList{
Object: map[string]interface{}{
"apiVersion": "vTest",
"kind": "rTestList",
},
Items: []unstructured.Unstructured{
*getObject("vTest", "rTest", "item1"),
*getObject("vTest", "rTest", "item2"),
},
},
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("List(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
w.Write(tc.resp)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("List(%q) want: %v\ngot: %v", tc.name, tc.want, got)
}
}
}
func TestGet(t *testing.T) {
tcs := []struct {
resource string
namespace string
name string
path string
resp []byte
want *unstructured.Unstructured
}{
{
resource: "rtest",
name: "normal_get",
path: "/apis/gtest/vtest/rtest/normal_get",
resp: getJSON("vTest", "rTest", "normal_get"),
want: getObject("vTest", "rTest", "normal_get"),
},
{
resource: "rtest",
namespace: "nstest",
name: "namespaced_get",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_get",
resp: getJSON("vTest", "rTest", "namespaced_get"),
want: getObject("vTest", "rTest", "namespaced_get"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_get",
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
want: getObject("vTest", "srTest", "normal_subresource_get"),
},
{
resource: "rtest/srtest",
namespace: "nstest",
name: "namespaced_subresource_get",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Get(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
w.Write(tc.resp)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{})
if err != nil {
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Get(%q) want: %v\ngot: %v", tc.name, tc.want, got)
}
}
}
func TestDelete(t *testing.T) {
background := metav1.DeletePropagationBackground
uid := types.UID("uid")
statusOK := &metav1.Status{
TypeMeta: metav1.TypeMeta{Kind: "Status"},
Status: metav1.StatusSuccess,
}
tcs := []struct {
namespace string
name string
path string
deleteOptions *metav1.DeleteOptions
}{
{
name: "normal_delete",
path: "/apis/gtest/vtest/rtest/normal_delete",
},
{
namespace: "nstest",
name: "namespaced_delete",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
},
{
namespace: "nstest",
name: "namespaced_delete_with_options",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete_with_options",
deleteOptions: &metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &uid}, PropagationPolicy: &background},
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Delete(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
unstructured.UnstructuredJSONScheme.Encode(statusOK, w)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
err = cl.Resource(resource, tc.namespace).Delete(tc.name, tc.deleteOptions)
if err != nil {
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
continue
}
}
}
func TestDeleteCollection(t *testing.T) {
statusOK := &metav1.Status{
TypeMeta: metav1.TypeMeta{Kind: "Status"},
Status: metav1.StatusSuccess,
}
tcs := []struct {
namespace string
name string
path string
}{
{
name: "normal_delete_collection",
path: "/apis/gtest/vtest/rtest",
},
{
namespace: "nstest",
name: "namespaced_delete_collection",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("DeleteCollection(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
unstructured.UnstructuredJSONScheme.Encode(statusOK, w)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
continue
}
}
}
func TestCreate(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
obj *unstructured.Unstructured
path string
}{
{
resource: "rtest",
name: "normal_create",
path: "/apis/gtest/vtest/rtest",
obj: getObject("gtest/vTest", "rTest", "normal_create"),
},
{
resource: "rtest",
name: "namespaced_create",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
obj: getObject("gtest/vTest", "rTest", "namespaced_create"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Create(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
data, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Create(%q) unexpected error reading body: %v", tc.name, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(data)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Create(tc.obj)
if err != nil {
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.obj) {
t.Errorf("Create(%q) want: %v\ngot: %v", tc.name, tc.obj, got)
}
}
}
func TestUpdate(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
obj *unstructured.Unstructured
path string
}{
{
resource: "rtest",
name: "normal_update",
path: "/apis/gtest/vtest/rtest/normal_update",
obj: getObject("gtest/vTest", "rTest", "normal_update"),
},
{
resource: "rtest",
name: "namespaced_update",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update",
obj: getObject("gtest/vTest", "rTest", "namespaced_update"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_update",
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
obj: getObject("gtest/vTest", "srTest", "normal_update"),
},
{
resource: "rtest/srtest",
name: "namespaced_subresource_update",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Update(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
w.Header().Set("Content-Type", runtime.ContentTypeJSON)
data, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Update(%q) unexpected error reading body: %v", tc.name, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Write(data)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Update(tc.obj)
if err != nil {
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.obj) {
t.Errorf("Update(%q) want: %v\ngot: %v", tc.name, tc.obj, got)
}
}
}
func TestWatch(t *testing.T) {
tcs := []struct {
name string
namespace string
events []watch.Event
path string
query string
}{
{
name: "normal_watch",
path: "/apis/gtest/vtest/rtest",
query: "watch=true",
events: []watch.Event{
{Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
{Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
{Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "normal_watch")},
},
},
{
name: "namespaced_watch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
query: "watch=true",
events: []watch.Event{
{Type: watch.Added, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
{Type: watch.Modified, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
{Type: watch.Deleted, Object: getObject("gtest/vTest", "rTest", "namespaced_watch")},
},
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Watch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
if r.URL.RawQuery != tc.query {
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
}
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{})
for _, e := range tc.events {
enc.Encode(&e)
}
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
continue
}
for _, want := range tc.events {
got := <-watcher.ResultChan()
if !reflect.DeepEqual(got, want) {
t.Errorf("Watch(%q) want: %v\ngot: %v", tc.name, want, got)
}
}
}
}
func TestPatch(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
patch []byte
want *unstructured.Unstructured
path string
}{
{
resource: "rtest",
name: "normal_patch",
path: "/apis/gtest/vtest/rtest/normal_patch",
patch: getJSON("gtest/vTest", "rTest", "normal_patch"),
want: getObject("gtest/vTest", "rTest", "normal_patch"),
},
{
resource: "rtest",
name: "namespaced_patch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_patch",
patch: getJSON("gtest/vTest", "rTest", "namespaced_patch"),
want: getObject("gtest/vTest", "rTest", "namespaced_patch"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_patch",
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
},
{
resource: "rtest/srtest",
name: "namespaced_subresource_patch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PATCH" {
t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method)
}
if r.URL.Path != tc.path {
t.Errorf("Patch(%q) got path %s. wanted %s", tc.name, r.URL.Path, tc.path)
}
content := r.Header.Get("Content-Type")
if content != string(types.StrategicMergePatchType) {
t.Errorf("Patch(%q) got Content-Type %s. wanted %s", tc.name, content, types.StrategicMergePatchType)
}
data, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Patch(%q) unexpected error reading body: %v", tc.name, err)
w.WriteHeader(http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(data)
})
if err != nil {
t.Errorf("unexpected error when creating client: %v", err)
continue
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch)
if err != nil {
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
continue
}
if !reflect.DeepEqual(got, tc.want) {
t.Errorf("Patch(%q) want: %v\ngot: %v", tc.name, tc.want, got)
}
}
}

View File

@@ -96,18 +96,12 @@ func (d *memCacheClient) RESTClient() restclient.Interface {
return d.delegate.RESTClient()
}
// TODO: Should this also be cached? The results seem more likely to be
// inconsistent with ServerGroups and ServerResources given the requirement to
// actively Invalidate.
func (d *memCacheClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
return d.delegate.ServerPreferredResources()
return discovery.ServerPreferredResources(d)
}
// TODO: Should this also be cached? The results seem more likely to be
// inconsistent with ServerGroups and ServerResources given the requirement to
// actively Invalidate.
func (d *memCacheClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
return d.delegate.ServerPreferredNamespacedResources()
return discovery.ServerPreferredNamespacedResources(d)
}
func (d *memCacheClient) ServerVersion() (*version.Info, error) {

View File

@@ -0,0 +1,282 @@
/*
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 discovery
import (
"errors"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"sync"
"time"
"github.com/golang/glog"
"github.com/googleapis/gnostic/OpenAPIv2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
)
// CachedDiscoveryClient implements the functions that discovery server-supported API groups,
// versions and resources.
type CachedDiscoveryClient struct {
delegate DiscoveryInterface
// cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well.
cacheDirectory string
// ttl is how long the cache should be considered valid
ttl time.Duration
// mutex protects the variables below
mutex sync.Mutex
// ourFiles are all filenames of cache files created by this process
ourFiles map[string]struct{}
// invalidated is true if all cache files should be ignored that are not ours (e.g. after Invalidate() was called)
invalidated bool
// fresh is true if all used cache files were ours
fresh bool
}
var _ CachedDiscoveryInterface = &CachedDiscoveryClient{}
// ServerResourcesForGroupVersion returns the supported resources for a group and version.
func (d *CachedDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
filename := filepath.Join(d.cacheDirectory, groupVersion, "serverresources.json")
cachedBytes, err := d.getCachedFile(filename)
// don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback.
if err == nil {
cachedResources := &metav1.APIResourceList{}
if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedResources); err == nil {
glog.V(10).Infof("returning cached discovery info from %v", filename)
return cachedResources, nil
}
}
liveResources, err := d.delegate.ServerResourcesForGroupVersion(groupVersion)
if err != nil {
glog.V(3).Infof("skipped caching discovery info due to %v", err)
return liveResources, err
}
if liveResources == nil || len(liveResources.APIResources) == 0 {
glog.V(3).Infof("skipped caching discovery info, no resources found")
return liveResources, err
}
if err := d.writeCachedFile(filename, liveResources); err != nil {
glog.V(3).Infof("failed to write cache to %v due to %v", filename, err)
}
return liveResources, nil
}
// ServerResources returns the supported resources for all groups and versions.
func (d *CachedDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) {
return ServerResources(d)
}
func (d *CachedDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) {
filename := filepath.Join(d.cacheDirectory, "servergroups.json")
cachedBytes, err := d.getCachedFile(filename)
// don't fail on errors, we either don't have a file or won't be able to run the cached check. Either way we can fallback.
if err == nil {
cachedGroups := &metav1.APIGroupList{}
if err := runtime.DecodeInto(scheme.Codecs.UniversalDecoder(), cachedBytes, cachedGroups); err == nil {
glog.V(10).Infof("returning cached discovery info from %v", filename)
return cachedGroups, nil
}
}
liveGroups, err := d.delegate.ServerGroups()
if err != nil {
glog.V(3).Infof("skipped caching discovery info due to %v", err)
return liveGroups, err
}
if liveGroups == nil || len(liveGroups.Groups) == 0 {
glog.V(3).Infof("skipped caching discovery info, no groups found")
return liveGroups, err
}
if err := d.writeCachedFile(filename, liveGroups); err != nil {
glog.V(3).Infof("failed to write cache to %v due to %v", filename, err)
}
return liveGroups, nil
}
func (d *CachedDiscoveryClient) getCachedFile(filename string) ([]byte, error) {
// after invalidation ignore cache files not created by this process
d.mutex.Lock()
_, ourFile := d.ourFiles[filename]
if d.invalidated && !ourFile {
d.mutex.Unlock()
return nil, errors.New("cache invalidated")
}
d.mutex.Unlock()
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()
fileInfo, err := file.Stat()
if err != nil {
return nil, err
}
if time.Now().After(fileInfo.ModTime().Add(d.ttl)) {
return nil, errors.New("cache expired")
}
// the cache is present and its valid. Try to read and use it.
cachedBytes, err := ioutil.ReadAll(file)
if err != nil {
return nil, err
}
d.mutex.Lock()
defer d.mutex.Unlock()
d.fresh = d.fresh && ourFile
return cachedBytes, nil
}
func (d *CachedDiscoveryClient) writeCachedFile(filename string, obj runtime.Object) error {
if err := os.MkdirAll(filepath.Dir(filename), 0755); err != nil {
return err
}
bytes, err := runtime.Encode(scheme.Codecs.LegacyCodec(), obj)
if err != nil {
return err
}
f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+".")
if err != nil {
return err
}
defer os.Remove(f.Name())
_, err = f.Write(bytes)
if err != nil {
return err
}
err = os.Chmod(f.Name(), 0755)
if err != nil {
return err
}
name := f.Name()
err = f.Close()
if err != nil {
return err
}
// atomic rename
d.mutex.Lock()
defer d.mutex.Unlock()
err = os.Rename(name, filename)
if err == nil {
d.ourFiles[filename] = struct{}{}
}
return err
}
func (d *CachedDiscoveryClient) RESTClient() restclient.Interface {
return d.delegate.RESTClient()
}
func (d *CachedDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
return ServerPreferredResources(d)
}
func (d *CachedDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
return ServerPreferredNamespacedResources(d)
}
func (d *CachedDiscoveryClient) ServerVersion() (*version.Info, error) {
return d.delegate.ServerVersion()
}
func (d *CachedDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
return d.delegate.OpenAPISchema()
}
func (d *CachedDiscoveryClient) Fresh() bool {
d.mutex.Lock()
defer d.mutex.Unlock()
return d.fresh
}
func (d *CachedDiscoveryClient) Invalidate() {
d.mutex.Lock()
defer d.mutex.Unlock()
d.ourFiles = map[string]struct{}{}
d.fresh = true
d.invalidated = true
}
// NewCachedDiscoveryClientForConfig creates a new DiscoveryClient for the given config, and wraps
// the created client in a CachedDiscoveryClient. The provided configuration is updated with a
// custom transport that understands cache responses.
// We receive two distinct cache directories for now, in order to preserve old behavior
// which makes use of the --cache-dir flag value for storing cache data from the CacheRoundTripper,
// and makes use of the hardcoded destination (~/.kube/cache/discovery/...) for storing
// CachedDiscoveryClient cache data. If httpCacheDir is empty, the restconfig's transport will not
// be updated with a roundtripper that understands cache responses.
// If discoveryCacheDir is empty, cached server resource data will be looked up in the current directory.
// TODO(juanvallejo): the value of "--cache-dir" should be honored. Consolidate discoveryCacheDir with httpCacheDir
// so that server resources and http-cache data are stored in the same location, provided via config flags.
func NewCachedDiscoveryClientForConfig(config *restclient.Config, discoveryCacheDir, httpCacheDir string, ttl time.Duration) (*CachedDiscoveryClient, error) {
if len(httpCacheDir) > 0 {
// update the given restconfig with a custom roundtripper that
// understands how to handle cache responses.
wt := config.WrapTransport
config.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
if wt != nil {
rt = wt(rt)
}
return newCacheRoundTripper(httpCacheDir, rt)
}
}
discoveryClient, err := NewDiscoveryClientForConfig(config)
if err != nil {
return nil, err
}
return newCachedDiscoveryClient(discoveryClient, discoveryCacheDir, ttl), nil
}
// NewCachedDiscoveryClient creates a new DiscoveryClient. cacheDirectory is the directory where discovery docs are held. It must be unique per host:port combination to work well.
func newCachedDiscoveryClient(delegate DiscoveryInterface, cacheDirectory string, ttl time.Duration) *CachedDiscoveryClient {
return &CachedDiscoveryClient{
delegate: delegate,
cacheDirectory: cacheDirectory,
ttl: ttl,
ourFiles: map[string]struct{}{},
fresh: true,
}
}

View File

@@ -0,0 +1,169 @@
/*
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 discovery
import (
"io/ioutil"
"os"
"testing"
"time"
"github.com/googleapis/gnostic/OpenAPIv2"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/version"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
)
func TestCachedDiscoveryClient_Fresh(t *testing.T) {
assert := assert.New(t)
d, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(d)
c := fakeDiscoveryClient{}
cdc := newCachedDiscoveryClient(&c, d, 60*time.Second)
assert.True(cdc.Fresh(), "should be fresh after creation")
cdc.ServerGroups()
assert.True(cdc.Fresh(), "should be fresh after groups call without cache")
assert.Equal(c.groupCalls, 1)
cdc.ServerGroups()
assert.True(cdc.Fresh(), "should be fresh after another groups call")
assert.Equal(c.groupCalls, 1)
cdc.ServerResources()
assert.True(cdc.Fresh(), "should be fresh after resources call")
assert.Equal(c.resourceCalls, 1)
cdc.ServerResources()
assert.True(cdc.Fresh(), "should be fresh after another resources call")
assert.Equal(c.resourceCalls, 1)
cdc = newCachedDiscoveryClient(&c, d, 60*time.Second)
cdc.ServerGroups()
assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing groups cache")
assert.Equal(c.groupCalls, 1)
cdc.ServerResources()
assert.False(cdc.Fresh(), "should NOT be fresh after recreation with existing resources cache")
assert.Equal(c.resourceCalls, 1)
cdc.Invalidate()
assert.True(cdc.Fresh(), "should be fresh after cache invalidation")
cdc.ServerResources()
assert.True(cdc.Fresh(), "should ignore existing resources cache after invalidation")
assert.Equal(c.resourceCalls, 2)
}
func TestNewCachedDiscoveryClient_TTL(t *testing.T) {
assert := assert.New(t)
d, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(d)
c := fakeDiscoveryClient{}
cdc := newCachedDiscoveryClient(&c, d, 1*time.Nanosecond)
cdc.ServerGroups()
assert.Equal(c.groupCalls, 1)
time.Sleep(1 * time.Second)
cdc.ServerGroups()
assert.Equal(c.groupCalls, 2)
}
type fakeDiscoveryClient struct {
groupCalls int
resourceCalls int
versionCalls int
openAPICalls int
serverResourcesHandler func() ([]*metav1.APIResourceList, error)
}
var _ DiscoveryInterface = &fakeDiscoveryClient{}
func (c *fakeDiscoveryClient) RESTClient() restclient.Interface {
return &fake.RESTClient{}
}
func (c *fakeDiscoveryClient) ServerGroups() (*metav1.APIGroupList, error) {
c.groupCalls = c.groupCalls + 1
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
{
Name: "a",
Versions: []metav1.GroupVersionForDiscovery{
{
GroupVersion: "a/v1",
Version: "v1",
},
},
PreferredVersion: metav1.GroupVersionForDiscovery{
GroupVersion: "a/v1",
Version: "v1",
},
},
},
}, nil
}
func (c *fakeDiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (*metav1.APIResourceList, error) {
c.resourceCalls = c.resourceCalls + 1
if groupVersion == "a/v1" {
return &metav1.APIResourceList{APIResources: []metav1.APIResource{{Name: "widgets", Kind: "Widget"}}}, nil
}
return nil, errors.NewNotFound(schema.GroupResource{}, "")
}
func (c *fakeDiscoveryClient) ServerResources() ([]*metav1.APIResourceList, error) {
c.resourceCalls = c.resourceCalls + 1
if c.serverResourcesHandler != nil {
return c.serverResourcesHandler()
}
return []*metav1.APIResourceList{}, nil
}
func (c *fakeDiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
c.resourceCalls = c.resourceCalls + 1
return nil, nil
}
func (c *fakeDiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
c.resourceCalls = c.resourceCalls + 1
return nil, nil
}
func (c *fakeDiscoveryClient) ServerVersion() (*version.Info, error) {
c.versionCalls = c.versionCalls + 1
return &version.Info{}, nil
}
func (c *fakeDiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
c.openAPICalls = c.openAPICalls + 1
return &openapi_v2.Document{}, nil
}

View File

@@ -22,6 +22,7 @@ import (
"net/url"
"sort"
"strings"
"sync"
"time"
"github.com/golang/protobuf/proto"
@@ -32,6 +33,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes/scheme"
restclient "k8s.io/client-go/rest"
@@ -42,12 +44,8 @@ const (
defaultRetries = 2
// protobuf mime type
mimePb = "application/com.github.proto-openapi.spec.v2@v1.0+protobuf"
)
var (
// defaultTimeout is the maximum amount of time per request when no timeout has been set on a RESTClient.
// Defaults to 32s in order to have a distinguishable length of time, relative to other timeouts that exist.
// It's a variable to be able to change it in tests.
defaultTimeout = 32 * time.Second
)
@@ -191,33 +189,7 @@ func (d *DiscoveryClient) ServerResourcesForGroupVersion(groupVersion string) (r
// serverResources returns the supported resources for all groups and versions.
func (d *DiscoveryClient) serverResources() ([]*metav1.APIResourceList, error) {
apiGroups, err := d.ServerGroups()
if err != nil {
return nil, err
}
result := []*metav1.APIResourceList{}
failedGroups := make(map[schema.GroupVersion]error)
for _, apiGroup := range apiGroups.Groups {
for _, version := range apiGroup.Versions {
gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
resources, err := d.ServerResourcesForGroupVersion(version.GroupVersion)
if err != nil {
// TODO: maybe restrict this to NotFound errors
failedGroups[gv] = err
continue
}
result = append(result, resources)
}
}
if len(failedGroups) == 0 {
return result, nil
}
return result, &ErrGroupDiscoveryFailed{Groups: failedGroups}
return ServerResources(d)
}
// ServerResources returns the supported resources for all groups and versions.
@@ -250,14 +222,46 @@ func IsGroupDiscoveryFailedError(err error) bool {
// serverPreferredResources returns the supported resources with the version preferred by the server.
func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList, error) {
return ServerPreferredResources(d)
}
// ServerResources uses the provided discovery interface to look up supported resources for all groups and versions.
func ServerResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) {
apiGroups, err := d.ServerGroups()
if err != nil {
return nil, err
}
groupVersionResources, failedGroups := fetchGroupVersionResources(d, apiGroups)
// order results by group/version discovery order
result := []*metav1.APIResourceList{}
for _, apiGroup := range apiGroups.Groups {
for _, version := range apiGroup.Versions {
gv := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
if resources, ok := groupVersionResources[gv]; ok {
result = append(result, resources)
}
}
}
if len(failedGroups) == 0 {
return result, nil
}
return result, &ErrGroupDiscoveryFailed{Groups: failedGroups}
}
// ServerPreferredResources uses the provided discovery interface to look up preferred resources
func ServerPreferredResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) {
serverGroupList, err := d.ServerGroups()
if err != nil {
return nil, err
}
result := []*metav1.APIResourceList{}
failedGroups := make(map[schema.GroupVersion]error)
groupVersionResources, failedGroups := fetchGroupVersionResources(d, serverGroupList)
result := []*metav1.APIResourceList{}
grVersions := map[schema.GroupResource]string{} // selected version of a GroupResource
grApiResources := map[schema.GroupResource]*metav1.APIResource{} // selected APIResource for a GroupResource
gvApiResourceLists := map[schema.GroupVersion]*metav1.APIResourceList{} // blueprint for a APIResourceList for later grouping
@@ -265,10 +269,9 @@ func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList,
for _, apiGroup := range serverGroupList.Groups {
for _, version := range apiGroup.Versions {
groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
apiResourceList, err := d.ServerResourcesForGroupVersion(version.GroupVersion)
if err != nil {
// TODO: maybe restrict this to NotFound errors
failedGroups[groupVersion] = err
apiResourceList, ok := groupVersionResources[groupVersion]
if !ok {
continue
}
@@ -310,6 +313,41 @@ func (d *DiscoveryClient) serverPreferredResources() ([]*metav1.APIResourceList,
return result, &ErrGroupDiscoveryFailed{Groups: failedGroups}
}
// fetchServerResourcesForGroupVersions uses the discovery client to fetch the resources for the specified groups in parallel
func fetchGroupVersionResources(d DiscoveryInterface, apiGroups *metav1.APIGroupList) (map[schema.GroupVersion]*metav1.APIResourceList, map[schema.GroupVersion]error) {
groupVersionResources := make(map[schema.GroupVersion]*metav1.APIResourceList)
failedGroups := make(map[schema.GroupVersion]error)
wg := &sync.WaitGroup{}
resultLock := &sync.Mutex{}
for _, apiGroup := range apiGroups.Groups {
for _, version := range apiGroup.Versions {
groupVersion := schema.GroupVersion{Group: apiGroup.Name, Version: version.Version}
wg.Add(1)
go func() {
defer wg.Done()
defer utilruntime.HandleCrash()
apiResourceList, err := d.ServerResourcesForGroupVersion(groupVersion.String())
// lock to record results
resultLock.Lock()
defer resultLock.Unlock()
if err != nil {
// TODO: maybe restrict this to NotFound errors
failedGroups[groupVersion] = err
} else {
groupVersionResources[groupVersion] = apiResourceList
}
}()
}
}
wg.Wait()
return groupVersionResources, failedGroups
}
// ServerPreferredResources returns the supported resources with the version preferred by the
// server.
func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList, error) {
@@ -319,7 +357,12 @@ func (d *DiscoveryClient) ServerPreferredResources() ([]*metav1.APIResourceList,
// ServerPreferredNamespacedResources returns the supported namespaced resources with the
// version preferred by the server.
func (d *DiscoveryClient) ServerPreferredNamespacedResources() ([]*metav1.APIResourceList, error) {
all, err := d.ServerPreferredResources()
return ServerPreferredNamespacedResources(d)
}
// ServerPreferredNamespacedResources uses the provided discovery interface to look up preferred namespaced resources
func ServerPreferredNamespacedResources(d DiscoveryInterface) ([]*metav1.APIResourceList, error) {
all, err := ServerPreferredResources(d)
return FilteredBy(ResourcePredicateFunc(func(groupVersion string, r *metav1.APIResource) bool {
return r.Namespaced
}), all), err

View File

@@ -23,15 +23,15 @@ import (
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
"github.com/gogo/protobuf/proto"
"github.com/googleapis/gnostic/OpenAPIv2"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/version"
restclient "k8s.io/client-go/rest"
@@ -130,25 +130,11 @@ func TestGetServerGroupsWithBrokenServer(t *testing.T) {
}
}
}
func TestGetServerGroupsWithTimeout(t *testing.T) {
done := make(chan bool)
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// first we need to write headers, otherwise http client will complain about
// exceeding timeout awaiting headers, only after we can block the call
w.WriteHeader(http.StatusOK)
<-done
}))
defer server.Close()
defer close(done)
tmp := defaultTimeout
defaultTimeout = 2 * time.Second
client := NewDiscoveryClientForConfigOrDie(&restclient.Config{Host: server.URL})
_, err := client.ServerGroups()
if err == nil || !strings.Contains(err.Error(), "deadline") {
t.Fatalf("unexpected error: %v", err)
}
done <- true
defaultTimeout = tmp
func TestTimeoutIsSet(t *testing.T) {
cfg := &restclient.Config{}
setDiscoveryDefaults(cfg)
assert.Equal(t, defaultTimeout, cfg.Timeout)
}
func TestGetServerResourcesWithV1Server(t *testing.T) {
@@ -204,6 +190,14 @@ func TestGetServerResources(t *testing.T) {
{Name: "jobs", Namespaced: true, Kind: "Job"},
},
}
beta2 := metav1.APIResourceList{
GroupVersion: "extensions/v1beta2",
APIResources: []metav1.APIResource{
{Name: "deployments", Namespaced: true, Kind: "Deployment"},
{Name: "ingresses", Namespaced: true, Kind: "Ingress"},
{Name: "jobs", Namespaced: true, Kind: "Job"},
},
}
tests := []struct {
resourcesList *metav1.APIResourceList
path string
@@ -236,6 +230,8 @@ func TestGetServerResources(t *testing.T) {
list = &stable
case "/apis/extensions/v1beta1":
list = &beta
case "/apis/extensions/v1beta2":
list = &beta2
case "/api":
list = &metav1.APIVersions{
Versions: []string{
@@ -246,8 +242,10 @@ func TestGetServerResources(t *testing.T) {
list = &metav1.APIGroupList{
Groups: []metav1.APIGroup{
{
Name: "extensions",
Versions: []metav1.GroupVersionForDiscovery{
{GroupVersion: "extensions/v1beta1"},
{GroupVersion: "extensions/v1beta1", Version: "v1beta1"},
{GroupVersion: "extensions/v1beta2", Version: "v1beta2"},
},
},
},
@@ -289,11 +287,10 @@ func TestGetServerResources(t *testing.T) {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
serverGroupVersions := sets.NewString(groupVersions(serverResources)...)
for _, api := range []string{"v1", "extensions/v1beta1"} {
if !serverGroupVersions.Has(api) {
t.Errorf("missing expected api %q in %v", api, serverResources)
}
serverGroupVersions := groupVersions(serverResources)
expectedGroupVersions := []string{"v1", "extensions/v1beta1", "extensions/v1beta2"}
if !reflect.DeepEqual(expectedGroupVersions, serverGroupVersions) {
t.Errorf("unexpected group versions: %v", diff.ObjectReflectDiff(expectedGroupVersions, serverGroupVersions))
}
}
@@ -639,7 +636,7 @@ func TestServerPreferredResourcesRetries(t *testing.T) {
{
Name: "extensions",
Versions: []metav1.GroupVersionForDiscovery{
{GroupVersion: "extensions/v1beta1"},
{GroupVersion: "extensions/v1beta1", Version: "v1beta1"},
},
PreferredVersion: metav1.GroupVersionForDiscovery{
GroupVersion: "extensions/v1beta1",

View File

@@ -0,0 +1,51 @@
/*
Copyright 2017 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 transport provides a round tripper capable of caching HTTP responses.
package discovery
import (
"net/http"
"path/filepath"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"github.com/peterbourgon/diskv"
)
type cacheRoundTripper struct {
rt *httpcache.Transport
}
// newCacheRoundTripper creates a roundtripper that reads the ETag on
// response headers and send the If-None-Match header on subsequent
// corresponding requests.
func newCacheRoundTripper(cacheDir string, rt http.RoundTripper) http.RoundTripper {
d := diskv.New(diskv.Options{
BasePath: cacheDir,
TempDir: filepath.Join(cacheDir, ".diskv-temp"),
})
t := httpcache.NewTransport(diskcache.NewWithDiskv(d))
t.Transport = rt
return &cacheRoundTripper{rt: t}
}
func (rt *cacheRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
return rt.rt.RoundTrip(req)
}
func (rt *cacheRoundTripper) WrappedRoundTripper() http.RoundTripper { return rt.rt.Transport }

View File

@@ -0,0 +1,95 @@
/*
Copyright 2017 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 discovery
import (
"bytes"
"io/ioutil"
"net/http"
"net/url"
"os"
"testing"
)
// copied from k8s.io/client-go/transport/round_trippers_test.go
type testRoundTripper struct {
Request *http.Request
Response *http.Response
Err error
}
func (rt *testRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
rt.Request = req
return rt.Response, rt.Err
}
func TestCacheRoundTripper(t *testing.T) {
rt := &testRoundTripper{}
cacheDir, err := ioutil.TempDir("", "cache-rt")
defer os.RemoveAll(cacheDir)
if err != nil {
t.Fatal(err)
}
cache := newCacheRoundTripper(cacheDir, rt)
// First call, caches the response
req := &http.Request{
Method: http.MethodGet,
URL: &url.URL{Host: "localhost"},
}
rt.Response = &http.Response{
Header: http.Header{"ETag": []string{`"123456"`}},
Body: ioutil.NopCloser(bytes.NewReader([]byte("Content"))),
StatusCode: http.StatusOK,
}
resp, err := cache.RoundTrip(req)
if err != nil {
t.Fatal(err)
}
content, err := ioutil.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
if string(content) != "Content" {
t.Errorf(`Expected Body to be "Content", got %q`, string(content))
}
// Second call, returns cached response
req = &http.Request{
Method: http.MethodGet,
URL: &url.URL{Host: "localhost"},
}
rt.Response = &http.Response{
StatusCode: http.StatusNotModified,
Body: ioutil.NopCloser(bytes.NewReader([]byte("Other Content"))),
}
resp, err = cache.RoundTrip(req)
if err != nil {
t.Fatal(err)
}
// Read body and make sure we have the initial content
content, err = ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
t.Fatal(err)
}
if string(content) != "Content" {
t.Errorf("Invalid content read from cache %q", string(content))
}
}

View File

@@ -26,31 +26,17 @@ import (
// UnstructuredObjectTyper provides a runtime.ObjectTyper implementation for
// runtime.Unstructured object based on discovery information.
type UnstructuredObjectTyper struct {
registered map[schema.GroupVersionKind]bool
typers []runtime.ObjectTyper
typers []runtime.ObjectTyper
}
// NewUnstructuredObjectTyper returns a runtime.ObjectTyper for
// unstructured objects based on discovery information. It accepts a list of fallback typers
// for handling objects that are not runtime.Unstructured. It does not delegate the Recognizes
// check, only ObjectKinds.
func NewUnstructuredObjectTyper(groupResources []*APIGroupResources, typers ...runtime.ObjectTyper) *UnstructuredObjectTyper {
// TODO this only works for the apiextensions server and doesn't recognize any types. Move to point of use.
func NewUnstructuredObjectTyper(typers ...runtime.ObjectTyper) *UnstructuredObjectTyper {
dot := &UnstructuredObjectTyper{
registered: make(map[schema.GroupVersionKind]bool),
typers: typers,
}
for _, group := range groupResources {
for _, discoveryVersion := range group.Group.Versions {
resources, ok := group.VersionedResources[discoveryVersion.Version]
if !ok {
continue
}
gv := schema.GroupVersion{Group: group.Group.Name, Version: discoveryVersion.Version}
for _, resource := range resources {
dot.registered[gv.WithKind(resource.Kind)] = true
}
}
typers: typers,
}
return dot
}
@@ -89,7 +75,7 @@ func (d *UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) (gvks []schema
// Recognizes returns true if the provided group,version,kind was in the
// discovery information.
func (d *UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
return d.registered[gvk]
return false
}
var _ runtime.ObjectTyper = &UnstructuredObjectTyper{}

View File

@@ -58,12 +58,11 @@ func getObject(version, kind, name string) *unstructured.Unstructured {
}
}
func getClientServer(gv *schema.GroupVersion, h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) {
func getClientServer(h func(http.ResponseWriter, *http.Request)) (Interface, *httptest.Server, error) {
srv := httptest.NewServer(http.HandlerFunc(h))
cl, err := NewClient(&restclient.Config{
Host: srv.URL,
ContentConfig: restclient.ContentConfig{GroupVersion: gv},
}, *gv)
cl, err := NewForConfig(&restclient.Config{
Host: srv.URL,
})
if err != nil {
srv.Close()
return nil, nil, err
@@ -116,9 +115,8 @@ func TestList(t *testing.T) {
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("List(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
@@ -136,7 +134,7 @@ func TestList(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).List(metav1.ListOptions{})
got, err := cl.Resource(resource).Namespace(tc.namespace).List(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when listing %q: %v", tc.name, err)
continue
@@ -150,12 +148,13 @@ func TestList(t *testing.T) {
func TestGet(t *testing.T) {
tcs := []struct {
resource string
namespace string
name string
path string
resp []byte
want *unstructured.Unstructured
resource string
subresource []string
namespace string
name string
path string
resp []byte
want *unstructured.Unstructured
}{
{
resource: "rtest",
@@ -173,25 +172,26 @@ func TestGet(t *testing.T) {
want: getObject("vTest", "rTest", "namespaced_get"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_get",
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
want: getObject("vTest", "srTest", "normal_subresource_get"),
resource: "rtest",
subresource: []string{"srtest"},
name: "normal_subresource_get",
path: "/apis/gtest/vtest/rtest/normal_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "normal_subresource_get"),
want: getObject("vTest", "srTest", "normal_subresource_get"),
},
{
resource: "rtest/srtest",
namespace: "nstest",
name: "namespaced_subresource_get",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
resource: "rtest",
subresource: []string{"srtest"},
namespace: "nstest",
name: "namespaced_subresource_get",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_get/srtest",
resp: getJSON("vTest", "srTest", "namespaced_subresource_get"),
want: getObject("vTest", "srTest", "namespaced_subresource_get"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("Get(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
@@ -209,7 +209,7 @@ func TestGet(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Get(tc.name, metav1.GetOptions{})
got, err := cl.Resource(resource).Namespace(tc.namespace).Get(tc.name, metav1.GetOptions{}, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when getting %q: %v", tc.name, err)
continue
@@ -230,6 +230,7 @@ func TestDelete(t *testing.T) {
Status: metav1.StatusSuccess,
}
tcs := []struct {
subresource []string
namespace string
name string
path string
@@ -244,6 +245,17 @@ func TestDelete(t *testing.T) {
name: "namespaced_delete",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete",
},
{
subresource: []string{"srtest"},
name: "normal_delete",
path: "/apis/gtest/vtest/rtest/normal_delete/srtest",
},
{
subresource: []string{"srtest"},
namespace: "nstest",
name: "namespaced_delete",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_delete/srtest",
},
{
namespace: "nstest",
name: "namespaced_delete_with_options",
@@ -252,9 +264,8 @@ func TestDelete(t *testing.T) {
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("Delete(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
}
@@ -272,7 +283,7 @@ func TestDelete(t *testing.T) {
}
defer srv.Close()
err = cl.Resource(resource, tc.namespace).Delete(tc.name, tc.deleteOptions)
err = cl.Resource(resource).Namespace(tc.namespace).Delete(tc.name, tc.deleteOptions, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when deleting %q: %v", tc.name, err)
continue
@@ -301,9 +312,8 @@ func TestDeleteCollection(t *testing.T) {
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "DELETE" {
t.Errorf("DeleteCollection(%q) got HTTP method %s. wanted DELETE", tc.name, r.Method)
}
@@ -321,7 +331,7 @@ func TestDeleteCollection(t *testing.T) {
}
defer srv.Close()
err = cl.Resource(resource, tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
err = cl.Resource(resource).Namespace(tc.namespace).DeleteCollection(nil, metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when deleting collection %q: %v", tc.name, err)
continue
@@ -331,11 +341,12 @@ func TestDeleteCollection(t *testing.T) {
func TestCreate(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
obj *unstructured.Unstructured
path string
resource string
subresource []string
name string
namespace string
obj *unstructured.Unstructured
path string
}{
{
resource: "rtest",
@@ -350,11 +361,25 @@ func TestCreate(t *testing.T) {
path: "/apis/gtest/vtest/namespaces/nstest/rtest",
obj: getObject("gtest/vTest", "rTest", "namespaced_create"),
},
{
resource: "rtest",
subresource: []string{"srtest"},
name: "normal_subresource_create",
path: "/apis/gtest/vtest/rtest/normal_subresource_create/srtest",
obj: getObject("vTest", "srTest", "normal_subresource_create"),
},
{
resource: "rtest/",
subresource: []string{"srtest"},
name: "namespaced_subresource_create",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_create/srtest",
obj: getObject("vTest", "srTest", "namespaced_subresource_create"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
t.Errorf("Create(%q) got HTTP method %s. wanted POST", tc.name, r.Method)
}
@@ -379,7 +404,7 @@ func TestCreate(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Create(tc.obj)
got, err := cl.Resource(resource).Namespace(tc.namespace).Create(tc.obj, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when creating %q: %v", tc.name, err)
continue
@@ -393,11 +418,12 @@ func TestCreate(t *testing.T) {
func TestUpdate(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
obj *unstructured.Unstructured
path string
resource string
subresource []string
name string
namespace string
obj *unstructured.Unstructured
path string
}{
{
resource: "rtest",
@@ -413,23 +439,24 @@ func TestUpdate(t *testing.T) {
obj: getObject("gtest/vTest", "rTest", "namespaced_update"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_update",
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
obj: getObject("gtest/vTest", "srTest", "normal_update"),
resource: "rtest",
subresource: []string{"srtest"},
name: "normal_subresource_update",
path: "/apis/gtest/vtest/rtest/normal_update/srtest",
obj: getObject("gtest/vTest", "srTest", "normal_update"),
},
{
resource: "rtest/srtest",
name: "namespaced_subresource_update",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
resource: "rtest",
subresource: []string{"srtest"},
name: "namespaced_subresource_update",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_update/srtest",
obj: getObject("gtest/vTest", "srTest", "namespaced_update"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
t.Errorf("Update(%q) got HTTP method %s. wanted PUT", tc.name, r.Method)
}
@@ -454,7 +481,7 @@ func TestUpdate(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Update(tc.obj)
got, err := cl.Resource(resource).Namespace(tc.namespace).Update(tc.obj, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when updating %q: %v", tc.name, err)
continue
@@ -497,9 +524,8 @@ func TestWatch(t *testing.T) {
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: "rtest", Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: "rtest"}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
t.Errorf("Watch(%q) got HTTP method %s. wanted GET", tc.name, r.Method)
}
@@ -511,7 +537,7 @@ func TestWatch(t *testing.T) {
t.Errorf("Watch(%q) got query %s. wanted %s", tc.name, r.URL.RawQuery, tc.query)
}
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, dynamicCodec{}), dynamicCodec{})
enc := restclientwatch.NewEncoder(streaming.NewEncoder(w, unstructured.UnstructuredJSONScheme), unstructured.UnstructuredJSONScheme)
for _, e := range tc.events {
enc.Encode(&e)
}
@@ -522,7 +548,7 @@ func TestWatch(t *testing.T) {
}
defer srv.Close()
watcher, err := cl.Resource(resource, tc.namespace).Watch(metav1.ListOptions{})
watcher, err := cl.Resource(resource).Namespace(tc.namespace).Watch(metav1.ListOptions{})
if err != nil {
t.Errorf("unexpected error when watching %q: %v", tc.name, err)
continue
@@ -539,12 +565,13 @@ func TestWatch(t *testing.T) {
func TestPatch(t *testing.T) {
tcs := []struct {
resource string
name string
namespace string
patch []byte
want *unstructured.Unstructured
path string
resource string
subresource []string
name string
namespace string
patch []byte
want *unstructured.Unstructured
path string
}{
{
resource: "rtest",
@@ -562,25 +589,26 @@ func TestPatch(t *testing.T) {
want: getObject("gtest/vTest", "rTest", "namespaced_patch"),
},
{
resource: "rtest/srtest",
name: "normal_subresource_patch",
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
resource: "rtest",
subresource: []string{"srtest"},
name: "normal_subresource_patch",
path: "/apis/gtest/vtest/rtest/normal_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "normal_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "normal_subresource_patch"),
},
{
resource: "rtest/srtest",
name: "namespaced_subresource_patch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
resource: "rtest",
subresource: []string{"srtest"},
name: "namespaced_subresource_patch",
namespace: "nstest",
path: "/apis/gtest/vtest/namespaces/nstest/rtest/namespaced_subresource_patch/srtest",
patch: getJSON("gtest/vTest", "srTest", "namespaced_subresource_patch"),
want: getObject("gtest/vTest", "srTest", "namespaced_subresource_patch"),
},
}
for _, tc := range tcs {
gv := &schema.GroupVersion{Group: "gtest", Version: "vtest"}
resource := &metav1.APIResource{Name: tc.resource, Namespaced: len(tc.namespace) != 0}
cl, srv, err := getClientServer(gv, func(w http.ResponseWriter, r *http.Request) {
resource := schema.GroupVersionResource{Group: "gtest", Version: "vtest", Resource: tc.resource}
cl, srv, err := getClientServer(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PATCH" {
t.Errorf("Patch(%q) got HTTP method %s. wanted PATCH", tc.name, r.Method)
}
@@ -610,7 +638,7 @@ func TestPatch(t *testing.T) {
}
defer srv.Close()
got, err := cl.Resource(resource, tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch)
got, err := cl.Resource(resource).Namespace(tc.namespace).Patch(tc.name, types.StrategicMergePatchType, tc.patch, tc.subresource...)
if err != nil {
t.Errorf("unexpected error when patching %q: %v", tc.name, err)
continue

View File

@@ -1,87 +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 dynamic
import (
"fmt"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// NewDiscoveryRESTMapper returns a RESTMapper based on discovery information.
func NewDiscoveryRESTMapper(resources []*metav1.APIResourceList) (*meta.DefaultRESTMapper, error) {
rm := meta.NewDefaultRESTMapper(nil)
for _, resourceList := range resources {
gv, err := schema.ParseGroupVersion(resourceList.GroupVersion)
if err != nil {
return nil, err
}
for _, resource := range resourceList.APIResources {
gvk := gv.WithKind(resource.Kind)
scope := meta.RESTScopeRoot
if resource.Namespaced {
scope = meta.RESTScopeNamespace
}
rm.Add(gvk, scope)
}
}
return rm, nil
}
// ObjectTyper provides an ObjectTyper implementation for
// unstructured.Unstructured object based on discovery information.
type ObjectTyper struct {
registered map[schema.GroupVersionKind]bool
}
// NewObjectTyper constructs an ObjectTyper from discovery information.
func NewObjectTyper(resources []*metav1.APIResourceList) (runtime.ObjectTyper, error) {
ot := &ObjectTyper{registered: make(map[schema.GroupVersionKind]bool)}
for _, resourceList := range resources {
gv, err := schema.ParseGroupVersion(resourceList.GroupVersion)
if err != nil {
return nil, err
}
for _, resource := range resourceList.APIResources {
ot.registered[gv.WithKind(resource.Kind)] = true
}
}
return ot, nil
}
// ObjectKinds returns a slice of one element with the
// group,version,kind of the provided object, or an error if the
// object is not *unstructured.Unstructured or has no group,version,kind
// information.
func (ot *ObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
if _, ok := obj.(*unstructured.Unstructured); !ok {
return nil, false, fmt.Errorf("type %T is invalid for determining dynamic object types", obj)
}
return []schema.GroupVersionKind{obj.GetObjectKind().GroupVersionKind()}, false, nil
}
// Recognizes returns true if the provided group,version,kind was in
// the discovery information.
func (ot *ObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
return ot.registered[gvk]
}

View File

@@ -1,79 +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 dynamic
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
func TestDiscoveryRESTMapper(t *testing.T) {
resources := []*metav1.APIResourceList{
{
GroupVersion: "test/beta1",
APIResources: []metav1.APIResource{
{
Name: "test_kinds",
Namespaced: true,
Kind: "test_kind",
},
},
},
}
gvk := schema.GroupVersionKind{
Group: "test",
Version: "beta1",
Kind: "test_kind",
}
mapper, err := NewDiscoveryRESTMapper(resources)
if err != nil {
t.Fatalf("unexpected error creating mapper: %s", err)
}
for _, res := range []schema.GroupVersionResource{
{
Group: "test",
Version: "beta1",
Resource: "test_kinds",
},
{
Version: "beta1",
Resource: "test_kinds",
},
{
Group: "test",
Resource: "test_kinds",
},
{
Resource: "test_kinds",
},
} {
got, err := mapper.KindFor(res)
if err != nil {
t.Errorf("KindFor(%#v) unexpected error: %s", res, err)
continue
}
if got != gvk {
t.Errorf("KindFor(%#v) = %#v; want %#v", res, got, gvk)
}
}
}

View File

@@ -1,163 +0,0 @@
/*
Copyright 2017 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 provides a fake client interface to arbitrary Kubernetes
// APIs that exposes common high level operations and exposes common
// metadata.
package fake
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/testing"
"k8s.io/client-go/util/flowcontrol"
)
// FakeClient is a fake implementation of dynamic.Interface.
type FakeClient struct {
GroupVersion schema.GroupVersion
*testing.Fake
}
// GetRateLimiter returns the rate limiter for this client.
func (c *FakeClient) GetRateLimiter() flowcontrol.RateLimiter {
return nil
}
// Resource returns an API interface to the specified resource for this client's
// group and version. If resource is not a namespaced resource, then namespace
// is ignored. The ResourceClient inherits the parameter codec of this client
func (c *FakeClient) Resource(resource *metav1.APIResource, namespace string) dynamic.ResourceInterface {
return &FakeResourceClient{
Resource: c.GroupVersion.WithResource(resource.Name),
Kind: c.GroupVersion.WithKind(resource.Kind),
Namespace: namespace,
Fake: c.Fake,
}
}
// ParameterCodec returns a client with the provided parameter codec.
func (c *FakeClient) ParameterCodec(parameterCodec runtime.ParameterCodec) dynamic.Interface {
return &FakeClient{
Fake: c.Fake,
}
}
// FakeResourceClient is a fake implementation of dynamic.ResourceInterface
type FakeResourceClient struct {
Resource schema.GroupVersionResource
Kind schema.GroupVersionKind
Namespace string
*testing.Fake
}
// List returns a list of objects for this resource.
func (c *FakeResourceClient) List(opts metav1.ListOptions) (runtime.Object, error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(c.Resource, c.Kind, c.Namespace, opts), &unstructured.UnstructuredList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &unstructured.UnstructuredList{}
for _, item := range obj.(*unstructured.UnstructuredList).Items {
if label.Matches(labels.Set(item.GetLabels())) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Get gets the resource with the specified name.
func (c *FakeResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{})
if obj == nil {
return nil, err
}
return obj.(*unstructured.Unstructured), err
}
// Delete deletes the resource with the specified name.
func (c *FakeResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(c.Resource, c.Namespace, name), &unstructured.Unstructured{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeResourceClient) DeleteCollection(deleteOptions *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteCollectionAction(c.Resource, c.Namespace, listOptions), &unstructured.Unstructured{})
return err
}
// Create creates the provided resource.
func (c *FakeResourceClient) Create(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{})
if obj == nil {
return nil, err
}
return obj.(*unstructured.Unstructured), err
}
// Update updates the provided resource.
func (c *FakeResourceClient) Update(inObj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(c.Resource, c.Namespace, inObj), &unstructured.Unstructured{})
if obj == nil {
return nil, err
}
return obj.(*unstructured.Unstructured), err
}
// Watch returns a watch.Interface that watches the resource.
func (c *FakeResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(c.Resource, c.Namespace, opts))
}
// Patch patches the provided resource.
func (c *FakeResourceClient) Patch(name string, pt types.PatchType, data []byte) (*unstructured.Unstructured, error) {
obj, err := c.Fake.
Invokes(testing.NewPatchAction(c.Resource, c.Namespace, name, data), &unstructured.Unstructured{})
if obj == nil {
return nil, err
}
return obj.(*unstructured.Unstructured), err
}

View File

@@ -1,48 +0,0 @@
/*
Copyright 2017 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 provides a fake client interface to arbitrary Kubernetes
// APIs that exposes common high level operations and exposes common
// metadata.
package fake
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/testing"
)
// FakeClientPool provides a fake implementation of dynamic.ClientPool.
// It assumes resource GroupVersions are the same as their corresponding kind GroupVersions.
type FakeClientPool struct {
testing.Fake
}
// ClientForGroupVersionKind returns a client configured for the specified groupVersionResource.
// Resource may be empty.
func (p *FakeClientPool) ClientForGroupVersionResource(resource schema.GroupVersionResource) (dynamic.Interface, error) {
return p.ClientForGroupVersionKind(resource.GroupVersion().WithKind(""))
}
// ClientForGroupVersionKind returns a client configured for the specified groupVersionKind.
// Kind may be empty.
func (p *FakeClientPool) ClientForGroupVersionKind(kind schema.GroupVersionKind) (dynamic.Interface, error) {
// we can just create a new client every time for testing purposes
return &FakeClient{
GroupVersion: kind.GroupVersion(),
Fake: &p.Fake,
}, nil
}

View File

@@ -17,6 +17,8 @@ limitations under the License.
package fake
import (
"strings"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -63,37 +65,54 @@ type FakeDynamicClient struct {
}
type dynamicResourceClient struct {
client *FakeDynamicClient
namespace string
resource schema.GroupVersionResource
subresource string
client *FakeDynamicClient
namespace string
resource schema.GroupVersionResource
}
var _ dynamic.DynamicInterface = &FakeDynamicClient{}
var _ dynamic.Interface = &FakeDynamicClient{}
func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableDynamicResourceInterface {
func (c *FakeDynamicClient) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
return &dynamicResourceClient{client: c, resource: resource}
}
// Deprecated, this isn't how we want to do it
func (c *FakeDynamicClient) ClusterSubresource(resource schema.GroupVersionResource, subresource string) dynamic.DynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, subresource: subresource}
}
// Deprecated, this isn't how we want to do it
func (c *FakeDynamicClient) NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) dynamic.DynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, namespace: namespace, subresource: subresource}
}
func (c *dynamicResourceClient) Namespace(ns string) dynamic.DynamicResourceInterface {
func (c *dynamicResourceClient) Namespace(ns string) dynamic.ResourceInterface {
ret := *c
ret.namespace = ns
return &ret
}
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
uncastRet, err := c.client.Fake.
Invokes(testing.NewCreateAction(c.resource, c.namespace, obj), obj)
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, 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
@@ -109,9 +128,27 @@ func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstruc
return ret, err
}
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
uncastRet, err := c.client.Fake.
Invokes(testing.NewUpdateAction(c.resource, c.namespace, obj), obj)
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, 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
@@ -128,8 +165,18 @@ func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstruc
}
func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
uncastRet, err := c.client.Fake.
Invokes(testing.NewUpdateSubresourceAction(c.resource, "status", c.namespace, obj), obj)
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
@@ -145,23 +192,65 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
return ret, err
}
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
_, err := c.client.Fake.
Invokes(testing.NewDeleteAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic delete fail"})
func (c *dynamicResourceClient) 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: "dynamic 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: "dynamic 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: "dynamic 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: "dynamic delete fail"})
}
return err
}
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
var err error
switch {
case len(c.namespace) == 0:
action := testing.NewRootDeleteCollectionAction(c.resource, listOptions)
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
case len(c.namespace) > 0:
action := testing.NewDeleteCollectionAction(c.resource, c.namespace, listOptions)
_, err = c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
}
_, err := c.client.Fake.Invokes(action, &metav1.Status{Status: "dynamic deletecollection fail"})
return err
}
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
uncastRet, err := c.client.Fake.
Invokes(testing.NewGetAction(c.resource, c.namespace, name), &metav1.Status{Status: "dynamic get fail"})
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, 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: "dynamic 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: "dynamic 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: "dynamic 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: "dynamic get fail"})
}
if err != nil {
return nil, err
@@ -178,8 +267,18 @@ func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstr
}
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
obj, err := c.client.Fake.
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
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{Version: "v1", Kind: "List"}, opts), &metav1.Status{Status: "dynamic list fail"})
case len(c.namespace) > 0:
obj, err = c.client.Fake.
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
}
if obj == nil {
return nil, err
@@ -213,13 +312,41 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
}
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
return c.client.Fake.
InvokesWatch(testing.NewWatchAction(c.resource, c.namespace, opts))
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")
}
func (c *dynamicResourceClient) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error) {
uncastRet, err := c.client.Fake.
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
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, data), &metav1.Status{Status: "dynamic patch fail"})
case len(c.namespace) == 0 && len(subresources) > 0:
uncastRet, err = c.client.Fake.
Invokes(testing.NewRootPatchSubresourceAction(c.resource, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
case len(c.namespace) > 0 && len(subresources) == 0:
uncastRet, err = c.client.Fake.
Invokes(testing.NewPatchAction(c.resource, c.namespace, name, data), &metav1.Status{Status: "dynamic patch fail"})
case len(c.namespace) > 0 && len(subresources) > 0:
uncastRet, err = c.client.Fake.
Invokes(testing.NewPatchSubresourceAction(c.resource, c.namespace, name, data, subresources...), &metav1.Status{Status: "dynamic patch fail"})
}
if err != nil {
return nil, err

59
dynamic/interface.go Normal file
View File

@@ -0,0 +1,59 @@
/*
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 dynamic
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
)
type Interface interface {
Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface
}
type ResourceInterface interface {
Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
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) (*unstructured.Unstructured, error)
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error)
}
type NamespaceableResourceInterface interface {
Namespace(string) ResourceInterface
ResourceInterface
}
// APIPathResolverFunc knows how to convert a groupVersion to its API path. The Kind field is optional.
// TODO find a better place to move this for existing callers
type APIPathResolverFunc func(kind schema.GroupVersionKind) string
// LegacyAPIPathResolverFunc can resolve paths properly with the legacy API.
// TODO find a better place to move this for existing callers
func LegacyAPIPathResolverFunc(kind schema.GroupVersionKind) string {
if len(kind.Group) == 0 {
return "/api"
}
return "/apis"
}

View File

@@ -17,7 +17,6 @@ limitations under the License.
package dynamic
import (
"fmt"
"io"
"k8s.io/apimachinery/pkg/api/meta"
@@ -31,39 +30,13 @@ import (
"k8s.io/client-go/rest"
)
type DynamicInterface interface {
Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface
// Deprecated, this isn't how we want to do it
ClusterSubresource(resource schema.GroupVersionResource, subresource string) DynamicResourceInterface
// Deprecated, this isn't how we want to do it
NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) DynamicResourceInterface
}
type DynamicResourceInterface interface {
Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
UpdateStatus(obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
Delete(name string, options *metav1.DeleteOptions) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions) (*unstructured.Unstructured, error)
List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*unstructured.Unstructured, error)
}
type NamespaceableDynamicResourceInterface interface {
Namespace(string) DynamicResourceInterface
DynamicResourceInterface
}
type dynamicClient struct {
client *rest.RESTClient
}
var _ DynamicInterface = &dynamicClient{}
var _ Interface = &dynamicClient{}
func NewForConfig(inConfig *rest.Config) (DynamicInterface, error) {
func NewForConfig(inConfig *rest.Config) (Interface, error) {
config := rest.CopyConfig(inConfig)
// for serializing the options
config.GroupVersion = &schema.GroupVersion{}
@@ -84,40 +57,36 @@ func NewForConfig(inConfig *rest.Config) (DynamicInterface, error) {
}
type dynamicResourceClient struct {
client *dynamicClient
namespace string
resource schema.GroupVersionResource
subresource string
client *dynamicClient
namespace string
resource schema.GroupVersionResource
}
func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableDynamicResourceInterface {
func (c *dynamicClient) Resource(resource schema.GroupVersionResource) NamespaceableResourceInterface {
return &dynamicResourceClient{client: c, resource: resource}
}
func (c *dynamicClient) ClusterSubresource(resource schema.GroupVersionResource, subresource string) DynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, subresource: subresource}
}
func (c *dynamicClient) NamespacedSubresource(resource schema.GroupVersionResource, subresource, namespace string) DynamicResourceInterface {
return &dynamicResourceClient{client: c, resource: resource, namespace: namespace, subresource: subresource}
}
func (c *dynamicResourceClient) Namespace(ns string) DynamicResourceInterface {
func (c *dynamicResourceClient) Namespace(ns string) ResourceInterface {
ret := *c
ret.namespace = ns
return &ret
}
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
if len(c.subresource) > 0 {
return nil, fmt.Errorf("create not supported for subresources")
}
func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
outBytes, err := runtime.Encode(unstructured.UnstructuredJSONScheme, obj)
if err != nil {
return nil, err
}
name := ""
if len(subresources) > 0 {
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
}
name = accessor.GetName()
}
result := c.client.client.Post().AbsPath(c.makeURLSegments("")...).Body(outBytes).Do()
result := c.client.client.Post().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(outBytes).Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -133,7 +102,7 @@ func (c *dynamicResourceClient) Create(obj *unstructured.Unstructured) (*unstruc
return uncastObj.(*unstructured.Unstructured), nil
}
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error) {
accessor, err := meta.Accessor(obj)
if err != nil {
return nil, err
@@ -143,7 +112,7 @@ func (c *dynamicResourceClient) Update(obj *unstructured.Unstructured) (*unstruc
return nil, err
}
result := c.client.client.Put().AbsPath(c.makeURLSegments(accessor.GetName())...).Body(outBytes).Do()
result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), subresources...)...).Body(outBytes).Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -171,6 +140,10 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
}
result := c.client.client.Put().AbsPath(append(c.makeURLSegments(accessor.GetName()), "status")...).Body(outBytes).Do()
if err := result.Error(); err != nil {
return nil, err
}
retBytes, err := result.Raw()
if err != nil {
return nil, err
@@ -182,7 +155,7 @@ func (c *dynamicResourceClient) UpdateStatus(obj *unstructured.Unstructured) (*u
return uncastObj.(*unstructured.Unstructured), nil
}
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions) error {
func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions, subresources ...string) error {
if opts == nil {
opts = &metav1.DeleteOptions{}
}
@@ -191,15 +164,11 @@ func (c *dynamicResourceClient) Delete(name string, opts *metav1.DeleteOptions)
return err
}
result := c.client.client.Delete().AbsPath(c.makeURLSegments(name)...).Body(deleteOptionsByte).Do()
result := c.client.client.Delete().AbsPath(append(c.makeURLSegments(name), subresources...)...).Body(deleteOptionsByte).Do()
return result.Error()
}
func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
if len(c.subresource) > 0 {
return fmt.Errorf("deletecollection not supported for subresources")
}
if opts == nil {
opts = &metav1.DeleteOptions{}
}
@@ -212,8 +181,8 @@ func (c *dynamicResourceClient) DeleteCollection(opts *metav1.DeleteOptions, lis
return result.Error()
}
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstructured.Unstructured, error) {
result := c.client.client.Get().AbsPath(c.makeURLSegments(name)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
result := c.client.client.Get().AbsPath(append(c.makeURLSegments(name), subresources...)...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
if err := result.Error(); err != nil {
return nil, err
}
@@ -229,10 +198,6 @@ func (c *dynamicResourceClient) Get(name string, opts metav1.GetOptions) (*unstr
}
func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
if len(c.subresource) > 0 {
return nil, fmt.Errorf("list not supported for subresources")
}
result := c.client.client.Get().AbsPath(c.makeURLSegments("")...).SpecificallyVersionedParams(&opts, dynamicParameterCodec, versionV1).Do()
if err := result.Error(); err != nil {
return nil, err
@@ -257,10 +222,6 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
}
func (c *dynamicResourceClient) Watch(opts metav1.ListOptions) (watch.Interface, error) {
if len(c.subresource) > 0 {
return nil, fmt.Errorf("watch not supported for subresources")
}
internalGV := schema.GroupVersions{
{Group: c.resource.Group, Version: runtime.APIVersionInternal},
// always include the legacy group as a decoding target to handle non-error `Status` return types
@@ -320,15 +281,6 @@ func (c *dynamicResourceClient) makeURLSegments(name string) []string {
if len(name) > 0 {
url = append(url, name)
// subresources only work on things with names
if len(c.subresource) > 0 {
url = append(url, c.subresource)
}
} else {
if len(c.subresource) > 0 {
panic("somehow snuck a subresource and an empty name. programmer error")
}
}
return url

View File

@@ -41,6 +41,7 @@ import (
rbac_v1alpha1 "k8s.io/api/rbac/v1alpha1"
rbac_v1beta1 "k8s.io/api/rbac/v1beta1"
scheduling_v1alpha1 "k8s.io/api/scheduling/v1alpha1"
scheduling_v1beta1 "k8s.io/api/scheduling/v1beta1"
settings_v1alpha1 "k8s.io/api/settings/v1alpha1"
storage_v1 "k8s.io/api/storage/v1"
storage_v1alpha1 "k8s.io/api/storage/v1alpha1"
@@ -235,6 +236,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case scheduling_v1alpha1.SchemeGroupVersion.WithResource("priorityclasses"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1alpha1().PriorityClasses().Informer()}, nil
// Group=scheduling.k8s.io, Version=v1beta1
case scheduling_v1beta1.SchemeGroupVersion.WithResource("priorityclasses"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Scheduling().V1beta1().PriorityClasses().Informer()}, nil
// Group=settings.k8s.io, Version=v1alpha1
case settings_v1alpha1.SchemeGroupVersion.WithResource("podpresets"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Settings().V1alpha1().PodPresets().Informer()}, nil

View File

@@ -21,12 +21,15 @@ package scheduling
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
v1alpha1 "k8s.io/client-go/informers/scheduling/v1alpha1"
v1beta1 "k8s.io/client-go/informers/scheduling/v1beta1"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha1 provides access to shared informers for resources in V1alpha1.
V1alpha1() v1alpha1.Interface
// V1beta1 provides access to shared informers for resources in V1beta1.
V1beta1() v1beta1.Interface
}
type group struct {
@@ -44,3 +47,8 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
func (g *group) V1alpha1() v1alpha1.Interface {
return v1alpha1.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)
}

View File

@@ -0,0 +1,45 @@
/*
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 v1beta1
import (
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// PriorityClasses returns a PriorityClassInformer.
PriorityClasses() PriorityClassInformer
}
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}
}
// PriorityClasses returns a PriorityClassInformer.
func (v *version) PriorityClasses() PriorityClassInformer {
return &priorityClassInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
}

View File

@@ -0,0 +1,88 @@
/*
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 v1beta1
import (
time "time"
scheduling_v1beta1 "k8s.io/api/scheduling/v1beta1"
v1 "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"
v1beta1 "k8s.io/client-go/listers/scheduling/v1beta1"
cache "k8s.io/client-go/tools/cache"
)
// PriorityClassInformer provides access to a shared informer and lister for
// PriorityClasses.
type PriorityClassInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.PriorityClassLister
}
type priorityClassInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewPriorityClassInformer constructs a new informer for PriorityClass 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 NewPriorityClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredPriorityClassInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredPriorityClassInformer constructs a new informer for PriorityClass 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 NewFilteredPriorityClassInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.SchedulingV1beta1().PriorityClasses().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.SchedulingV1beta1().PriorityClasses().Watch(options)
},
},
&scheduling_v1beta1.PriorityClass{},
resyncPeriod,
indexers,
)
}
func (f *priorityClassInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredPriorityClassInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *priorityClassInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&scheduling_v1beta1.PriorityClass{}, f.defaultInformer)
}
func (f *priorityClassInformer) Lister() v1beta1.PriorityClassLister {
return v1beta1.NewPriorityClassLister(f.Informer().GetIndexer())
}

View File

@@ -44,6 +44,7 @@ import (
rbacv1alpha1 "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1"
rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1"
schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1"
storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1"
storagev1alpha1 "k8s.io/client-go/kubernetes/typed/storage/v1alpha1"
@@ -104,8 +105,9 @@ type Interface interface {
RbacV1beta1() rbacv1beta1.RbacV1beta1Interface
RbacV1alpha1() rbacv1alpha1.RbacV1alpha1Interface
SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1Interface
SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface
// Deprecated: please explicitly pick a version if possible.
Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface
Scheduling() schedulingv1beta1.SchedulingV1beta1Interface
SettingsV1alpha1() settingsv1alpha1.SettingsV1alpha1Interface
// Deprecated: please explicitly pick a version if possible.
Settings() settingsv1alpha1.SettingsV1alpha1Interface
@@ -144,6 +146,7 @@ type Clientset struct {
rbacV1beta1 *rbacv1beta1.RbacV1beta1Client
rbacV1alpha1 *rbacv1alpha1.RbacV1alpha1Client
schedulingV1alpha1 *schedulingv1alpha1.SchedulingV1alpha1Client
schedulingV1beta1 *schedulingv1beta1.SchedulingV1beta1Client
settingsV1alpha1 *settingsv1alpha1.SettingsV1alpha1Client
storageV1beta1 *storagev1beta1.StorageV1beta1Client
storageV1 *storagev1.StorageV1Client
@@ -348,10 +351,15 @@ func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1In
return c.schedulingV1alpha1
}
// SchedulingV1beta1 retrieves the SchedulingV1beta1Client
func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface {
return c.schedulingV1beta1
}
// Deprecated: Scheduling retrieves the default version of SchedulingClient.
// Please explicitly pick a version.
func (c *Clientset) Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface {
return c.schedulingV1alpha1
func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface {
return c.schedulingV1beta1
}
// SettingsV1alpha1 retrieves the SettingsV1alpha1Client
@@ -498,6 +506,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil {
return nil, err
}
cs.schedulingV1beta1, err = schedulingv1beta1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.settingsV1alpha1, err = settingsv1alpha1.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
@@ -550,6 +562,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
cs.rbacV1beta1 = rbacv1beta1.NewForConfigOrDie(c)
cs.rbacV1alpha1 = rbacv1alpha1.NewForConfigOrDie(c)
cs.schedulingV1alpha1 = schedulingv1alpha1.NewForConfigOrDie(c)
cs.schedulingV1beta1 = schedulingv1beta1.NewForConfigOrDie(c)
cs.settingsV1alpha1 = settingsv1alpha1.NewForConfigOrDie(c)
cs.storageV1beta1 = storagev1beta1.NewForConfigOrDie(c)
cs.storageV1 = storagev1.NewForConfigOrDie(c)
@@ -586,6 +599,7 @@ func New(c rest.Interface) *Clientset {
cs.rbacV1beta1 = rbacv1beta1.New(c)
cs.rbacV1alpha1 = rbacv1alpha1.New(c)
cs.schedulingV1alpha1 = schedulingv1alpha1.New(c)
cs.schedulingV1beta1 = schedulingv1beta1.New(c)
cs.settingsV1alpha1 = settingsv1alpha1.New(c)
cs.storageV1beta1 = storagev1beta1.New(c)
cs.storageV1 = storagev1.New(c)

View File

@@ -72,6 +72,8 @@ import (
fakerbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1/fake"
schedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1"
fakeschedulingv1alpha1 "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1/fake"
schedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
fakeschedulingv1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1/fake"
settingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1"
fakesettingsv1alpha1 "k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake"
storagev1 "k8s.io/client-go/kubernetes/typed/storage/v1"
@@ -310,9 +312,14 @@ func (c *Clientset) SchedulingV1alpha1() schedulingv1alpha1.SchedulingV1alpha1In
return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake}
}
// Scheduling retrieves the SchedulingV1alpha1Client
func (c *Clientset) Scheduling() schedulingv1alpha1.SchedulingV1alpha1Interface {
return &fakeschedulingv1alpha1.FakeSchedulingV1alpha1{Fake: &c.Fake}
// SchedulingV1beta1 retrieves the SchedulingV1beta1Client
func (c *Clientset) SchedulingV1beta1() schedulingv1beta1.SchedulingV1beta1Interface {
return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake}
}
// Scheduling retrieves the SchedulingV1beta1Client
func (c *Clientset) Scheduling() schedulingv1beta1.SchedulingV1beta1Interface {
return &fakeschedulingv1beta1.FakeSchedulingV1beta1{Fake: &c.Fake}
}
// SettingsV1alpha1 retrieves the SettingsV1alpha1Client

View File

@@ -43,6 +43,7 @@ import (
rbacv1alpha1 "k8s.io/api/rbac/v1alpha1"
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1"
schedulingv1beta1 "k8s.io/api/scheduling/v1beta1"
settingsv1alpha1 "k8s.io/api/settings/v1alpha1"
storagev1 "k8s.io/api/storage/v1"
storagev1alpha1 "k8s.io/api/storage/v1alpha1"
@@ -101,6 +102,7 @@ func AddToScheme(scheme *runtime.Scheme) {
rbacv1beta1.AddToScheme(scheme)
rbacv1alpha1.AddToScheme(scheme)
schedulingv1alpha1.AddToScheme(scheme)
schedulingv1beta1.AddToScheme(scheme)
settingsv1alpha1.AddToScheme(scheme)
storagev1beta1.AddToScheme(scheme)
storagev1.AddToScheme(scheme)

View File

@@ -43,6 +43,7 @@ import (
rbacv1alpha1 "k8s.io/api/rbac/v1alpha1"
rbacv1beta1 "k8s.io/api/rbac/v1beta1"
schedulingv1alpha1 "k8s.io/api/scheduling/v1alpha1"
schedulingv1beta1 "k8s.io/api/scheduling/v1beta1"
settingsv1alpha1 "k8s.io/api/settings/v1alpha1"
storagev1 "k8s.io/api/storage/v1"
storagev1alpha1 "k8s.io/api/storage/v1alpha1"
@@ -101,6 +102,7 @@ func AddToScheme(scheme *runtime.Scheme) {
rbacv1beta1.AddToScheme(scheme)
rbacv1alpha1.AddToScheme(scheme)
schedulingv1alpha1.AddToScheme(scheme)
schedulingv1beta1.AddToScheme(scheme)
settingsv1alpha1.AddToScheme(scheme)
storagev1beta1.AddToScheme(scheme)
storagev1.AddToScheme(scheme)

View File

@@ -59,7 +59,7 @@ func (c *FakeInitializerConfigurations) List(opts v1.ListOptions) (result *v1alp
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.InitializerConfigurationList{}
list := &v1alpha1.InitializerConfigurationList{ListMeta: obj.(*v1alpha1.InitializerConfigurationList).ListMeta}
for _, item := range obj.(*v1alpha1.InitializerConfigurationList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeMutatingWebhookConfigurations) List(opts v1.ListOptions) (result *v
if label == nil {
label = labels.Everything()
}
list := &v1beta1.MutatingWebhookConfigurationList{}
list := &v1beta1.MutatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.MutatingWebhookConfigurationList).ListMeta}
for _, item := range obj.(*v1beta1.MutatingWebhookConfigurationList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeValidatingWebhookConfigurations) List(opts v1.ListOptions) (result
if label == nil {
label = labels.Everything()
}
list := &v1beta1.ValidatingWebhookConfigurationList{}
list := &v1beta1.ValidatingWebhookConfigurationList{ListMeta: obj.(*v1beta1.ValidatingWebhookConfigurationList).ListMeta}
for _, item := range obj.(*v1beta1.ValidatingWebhookConfigurationList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *apps_v1.Con
if label == nil {
label = labels.Everything()
}
list := &apps_v1.ControllerRevisionList{}
list := &apps_v1.ControllerRevisionList{ListMeta: obj.(*apps_v1.ControllerRevisionList).ListMeta}
for _, item := range obj.(*apps_v1.ControllerRevisionList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *apps_v1.DaemonSetLis
if label == nil {
label = labels.Everything()
}
list := &apps_v1.DaemonSetList{}
list := &apps_v1.DaemonSetList{ListMeta: obj.(*apps_v1.DaemonSetList).ListMeta}
for _, item := range obj.(*apps_v1.DaemonSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *apps_v1.DeploymentL
if label == nil {
label = labels.Everything()
}
list := &apps_v1.DeploymentList{}
list := &apps_v1.DeploymentList{ListMeta: obj.(*apps_v1.DeploymentList).ListMeta}
for _, item := range obj.(*apps_v1.DeploymentList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *apps_v1.ReplicaSetL
if label == nil {
label = labels.Everything()
}
list := &apps_v1.ReplicaSetList{}
list := &apps_v1.ReplicaSetList{ListMeta: obj.(*apps_v1.ReplicaSetList).ListMeta}
for _, item := range obj.(*apps_v1.ReplicaSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *apps_v1.StatefulSe
if label == nil {
label = labels.Everything()
}
list := &apps_v1.StatefulSetList{}
list := &apps_v1.StatefulSetList{ListMeta: obj.(*apps_v1.StatefulSetList).ListMeta}
for _, item := range obj.(*apps_v1.StatefulSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta1.Con
if label == nil {
label = labels.Everything()
}
list := &v1beta1.ControllerRevisionList{}
list := &v1beta1.ControllerRevisionList{ListMeta: obj.(*v1beta1.ControllerRevisionList).ListMeta}
for _, item := range obj.(*v1beta1.ControllerRevisionList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentL
if label == nil {
label = labels.Everything()
}
list := &v1beta1.DeploymentList{}
list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta}
for _, item := range obj.(*v1beta1.DeploymentList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta1.StatefulSe
if label == nil {
label = labels.Everything()
}
list := &v1beta1.StatefulSetList{}
list := &v1beta1.StatefulSetList{ListMeta: obj.(*v1beta1.StatefulSetList).ListMeta}
for _, item := range obj.(*v1beta1.StatefulSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeControllerRevisions) List(opts v1.ListOptions) (result *v1beta2.Con
if label == nil {
label = labels.Everything()
}
list := &v1beta2.ControllerRevisionList{}
list := &v1beta2.ControllerRevisionList{ListMeta: obj.(*v1beta2.ControllerRevisionList).ListMeta}
for _, item := range obj.(*v1beta2.ControllerRevisionList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta2.DaemonSetLis
if label == nil {
label = labels.Everything()
}
list := &v1beta2.DaemonSetList{}
list := &v1beta2.DaemonSetList{ListMeta: obj.(*v1beta2.DaemonSetList).ListMeta}
for _, item := range obj.(*v1beta2.DaemonSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta2.DeploymentL
if label == nil {
label = labels.Everything()
}
list := &v1beta2.DeploymentList{}
list := &v1beta2.DeploymentList{ListMeta: obj.(*v1beta2.DeploymentList).ListMeta}
for _, item := range obj.(*v1beta2.DeploymentList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta2.ReplicaSetL
if label == nil {
label = labels.Everything()
}
list := &v1beta2.ReplicaSetList{}
list := &v1beta2.ReplicaSetList{ListMeta: obj.(*v1beta2.ReplicaSetList).ListMeta}
for _, item := range obj.(*v1beta2.ReplicaSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeStatefulSets) List(opts v1.ListOptions) (result *v1beta2.StatefulSe
if label == nil {
label = labels.Everything()
}
list := &v1beta2.StatefulSetList{}
list := &v1beta2.StatefulSetList{ListMeta: obj.(*v1beta2.StatefulSetList).ListMeta}
for _, item := range obj.(*v1beta2.StatefulSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *autosc
if label == nil {
label = labels.Everything()
}
list := &autoscaling_v1.HorizontalPodAutoscalerList{}
list := &autoscaling_v1.HorizontalPodAutoscalerList{ListMeta: obj.(*autoscaling_v1.HorizontalPodAutoscalerList).ListMeta}
for _, item := range obj.(*autoscaling_v1.HorizontalPodAutoscalerList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeHorizontalPodAutoscalers) List(opts v1.ListOptions) (result *v2beta
if label == nil {
label = labels.Everything()
}
list := &v2beta1.HorizontalPodAutoscalerList{}
list := &v2beta1.HorizontalPodAutoscalerList{ListMeta: obj.(*v2beta1.HorizontalPodAutoscalerList).ListMeta}
for _, item := range obj.(*v2beta1.HorizontalPodAutoscalerList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeJobs) List(opts v1.ListOptions) (result *batch_v1.JobList, err erro
if label == nil {
label = labels.Everything()
}
list := &batch_v1.JobList{}
list := &batch_v1.JobList{ListMeta: obj.(*batch_v1.JobList).ListMeta}
for _, item := range obj.(*batch_v1.JobList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v1beta1.CronJobList, e
if label == nil {
label = labels.Everything()
}
list := &v1beta1.CronJobList{}
list := &v1beta1.CronJobList{ListMeta: obj.(*v1beta1.CronJobList).ListMeta}
for _, item := range obj.(*v1beta1.CronJobList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeCronJobs) List(opts v1.ListOptions) (result *v2alpha1.CronJobList,
if label == nil {
label = labels.Everything()
}
list := &v2alpha1.CronJobList{}
list := &v2alpha1.CronJobList{ListMeta: obj.(*v2alpha1.CronJobList).ListMeta}
for _, item := range obj.(*v2alpha1.CronJobList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeCertificateSigningRequests) List(opts v1.ListOptions) (result *v1be
if label == nil {
label = labels.Everything()
}
list := &v1beta1.CertificateSigningRequestList{}
list := &v1beta1.CertificateSigningRequestList{ListMeta: obj.(*v1beta1.CertificateSigningRequestList).ListMeta}
for _, item := range obj.(*v1beta1.CertificateSigningRequestList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeComponentStatuses) List(opts v1.ListOptions) (result *core_v1.Compo
if label == nil {
label = labels.Everything()
}
list := &core_v1.ComponentStatusList{}
list := &core_v1.ComponentStatusList{ListMeta: obj.(*core_v1.ComponentStatusList).ListMeta}
for _, item := range obj.(*core_v1.ComponentStatusList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeConfigMaps) List(opts v1.ListOptions) (result *core_v1.ConfigMapLis
if label == nil {
label = labels.Everything()
}
list := &core_v1.ConfigMapList{}
list := &core_v1.ConfigMapList{ListMeta: obj.(*core_v1.ConfigMapList).ListMeta}
for _, item := range obj.(*core_v1.ConfigMapList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeEndpoints) List(opts v1.ListOptions) (result *core_v1.EndpointsList
if label == nil {
label = labels.Everything()
}
list := &core_v1.EndpointsList{}
list := &core_v1.EndpointsList{ListMeta: obj.(*core_v1.EndpointsList).ListMeta}
for _, item := range obj.(*core_v1.EndpointsList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *core_v1.EventList, err e
if label == nil {
label = labels.Everything()
}
list := &core_v1.EventList{}
list := &core_v1.EventList{ListMeta: obj.(*core_v1.EventList).ListMeta}
for _, item := range obj.(*core_v1.EventList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeLimitRanges) List(opts v1.ListOptions) (result *core_v1.LimitRangeL
if label == nil {
label = labels.Everything()
}
list := &core_v1.LimitRangeList{}
list := &core_v1.LimitRangeList{ListMeta: obj.(*core_v1.LimitRangeList).ListMeta}
for _, item := range obj.(*core_v1.LimitRangeList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeNamespaces) List(opts v1.ListOptions) (result *core_v1.NamespaceLis
if label == nil {
label = labels.Everything()
}
list := &core_v1.NamespaceList{}
list := &core_v1.NamespaceList{ListMeta: obj.(*core_v1.NamespaceList).ListMeta}
for _, item := range obj.(*core_v1.NamespaceList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
@@ -112,14 +112,6 @@ func (c *FakeNamespaces) Delete(name string, options *v1.DeleteOptions) error {
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeNamespaces) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(namespacesResource, listOptions)
_, err := c.Fake.Invokes(action, &core_v1.NamespaceList{})
return err
}
// Patch applies the patch and returns the patched namespace.
func (c *FakeNamespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *core_v1.Namespace, err error) {
obj, err := c.Fake.

View File

@@ -59,7 +59,7 @@ func (c *FakeNodes) List(opts v1.ListOptions) (result *core_v1.NodeList, err err
if label == nil {
label = labels.Everything()
}
list := &core_v1.NodeList{}
list := &core_v1.NodeList{ListMeta: obj.(*core_v1.NodeList).ListMeta}
for _, item := range obj.(*core_v1.NodeList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakePersistentVolumes) List(opts v1.ListOptions) (result *core_v1.Persi
if label == nil {
label = labels.Everything()
}
list := &core_v1.PersistentVolumeList{}
list := &core_v1.PersistentVolumeList{ListMeta: obj.(*core_v1.PersistentVolumeList).ListMeta}
for _, item := range obj.(*core_v1.PersistentVolumeList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakePersistentVolumeClaims) List(opts v1.ListOptions) (result *core_v1.
if label == nil {
label = labels.Everything()
}
list := &core_v1.PersistentVolumeClaimList{}
list := &core_v1.PersistentVolumeClaimList{ListMeta: obj.(*core_v1.PersistentVolumeClaimList).ListMeta}
for _, item := range obj.(*core_v1.PersistentVolumeClaimList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakePods) List(opts v1.ListOptions) (result *core_v1.PodList, err error
if label == nil {
label = labels.Everything()
}
list := &core_v1.PodList{}
list := &core_v1.PodList{ListMeta: obj.(*core_v1.PodList).ListMeta}
for _, item := range obj.(*core_v1.PodList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakePodTemplates) List(opts v1.ListOptions) (result *core_v1.PodTemplat
if label == nil {
label = labels.Everything()
}
list := &core_v1.PodTemplateList{}
list := &core_v1.PodTemplateList{ListMeta: obj.(*core_v1.PodTemplateList).ListMeta}
for _, item := range obj.(*core_v1.PodTemplateList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -63,7 +63,7 @@ func (c *FakeReplicationControllers) List(opts v1.ListOptions) (result *core_v1.
if label == nil {
label = labels.Everything()
}
list := &core_v1.ReplicationControllerList{}
list := &core_v1.ReplicationControllerList{ListMeta: obj.(*core_v1.ReplicationControllerList).ListMeta}
for _, item := range obj.(*core_v1.ReplicationControllerList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeResourceQuotas) List(opts v1.ListOptions) (result *core_v1.Resource
if label == nil {
label = labels.Everything()
}
list := &core_v1.ResourceQuotaList{}
list := &core_v1.ResourceQuotaList{ListMeta: obj.(*core_v1.ResourceQuotaList).ListMeta}
for _, item := range obj.(*core_v1.ResourceQuotaList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeSecrets) List(opts v1.ListOptions) (result *core_v1.SecretList, err
if label == nil {
label = labels.Everything()
}
list := &core_v1.SecretList{}
list := &core_v1.SecretList{ListMeta: obj.(*core_v1.SecretList).ListMeta}
for _, item := range obj.(*core_v1.SecretList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeServices) List(opts v1.ListOptions) (result *core_v1.ServiceList, e
if label == nil {
label = labels.Everything()
}
list := &core_v1.ServiceList{}
list := &core_v1.ServiceList{ListMeta: obj.(*core_v1.ServiceList).ListMeta}
for _, item := range obj.(*core_v1.ServiceList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
@@ -120,14 +120,6 @@ func (c *FakeServices) Delete(name string, options *v1.DeleteOptions) error {
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeServices) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(servicesResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &core_v1.ServiceList{})
return err
}
// Patch applies the patch and returns the patched service.
func (c *FakeServices) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *core_v1.Service, err error) {
obj, err := c.Fake.

View File

@@ -62,7 +62,7 @@ func (c *FakeServiceAccounts) List(opts v1.ListOptions) (result *core_v1.Service
if label == nil {
label = labels.Everything()
}
list := &core_v1.ServiceAccountList{}
list := &core_v1.ServiceAccountList{ListMeta: obj.(*core_v1.ServiceAccountList).ListMeta}
for _, item := range obj.(*core_v1.ServiceAccountList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -39,7 +39,6 @@ type NamespaceInterface interface {
Update(*v1.Namespace) (*v1.Namespace, error)
UpdateStatus(*v1.Namespace) (*v1.Namespace, error)
Delete(name string, options *meta_v1.DeleteOptions) error
DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
Get(name string, options meta_v1.GetOptions) (*v1.Namespace, error)
List(opts meta_v1.ListOptions) (*v1.NamespaceList, error)
Watch(opts meta_v1.ListOptions) (watch.Interface, error)
@@ -139,16 +138,6 @@ func (c *namespaces) Delete(name string, options *meta_v1.DeleteOptions) error {
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *namespaces) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error {
return c.client.Delete().
Resource("namespaces").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched namespace.
func (c *namespaces) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Namespace, err error) {
result = &v1.Namespace{}

View File

@@ -39,7 +39,6 @@ type ServiceInterface interface {
Update(*v1.Service) (*v1.Service, error)
UpdateStatus(*v1.Service) (*v1.Service, error)
Delete(name string, options *meta_v1.DeleteOptions) error
DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
Get(name string, options meta_v1.GetOptions) (*v1.Service, error)
List(opts meta_v1.ListOptions) (*v1.ServiceList, error)
Watch(opts meta_v1.ListOptions) (watch.Interface, error)
@@ -148,17 +147,6 @@ func (c *services) Delete(name string, options *meta_v1.DeleteOptions) error {
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *services) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("services").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched service.
func (c *services) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Service, err error) {
result = &v1.Service{}

View File

@@ -62,7 +62,7 @@ func (c *FakeEvents) List(opts v1.ListOptions) (result *v1beta1.EventList, err e
if label == nil {
label = labels.Everything()
}
list := &v1beta1.EventList{}
list := &v1beta1.EventList{ListMeta: obj.(*v1beta1.EventList).ListMeta}
for _, item := range obj.(*v1beta1.EventList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDaemonSets) List(opts v1.ListOptions) (result *v1beta1.DaemonSetLis
if label == nil {
label = labels.Everything()
}
list := &v1beta1.DaemonSetList{}
list := &v1beta1.DaemonSetList{ListMeta: obj.(*v1beta1.DaemonSetList).ListMeta}
for _, item := range obj.(*v1beta1.DaemonSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeDeployments) List(opts v1.ListOptions) (result *v1beta1.DeploymentL
if label == nil {
label = labels.Everything()
}
list := &v1beta1.DeploymentList{}
list := &v1beta1.DeploymentList{ListMeta: obj.(*v1beta1.DeploymentList).ListMeta}
for _, item := range obj.(*v1beta1.DeploymentList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeIngresses) List(opts v1.ListOptions) (result *v1beta1.IngressList,
if label == nil {
label = labels.Everything()
}
list := &v1beta1.IngressList{}
list := &v1beta1.IngressList{ListMeta: obj.(*v1beta1.IngressList).ListMeta}
for _, item := range obj.(*v1beta1.IngressList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.Pod
if label == nil {
label = labels.Everything()
}
list := &v1beta1.PodSecurityPolicyList{}
list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta}
for _, item := range obj.(*v1beta1.PodSecurityPolicyList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeReplicaSets) List(opts v1.ListOptions) (result *v1beta1.ReplicaSetL
if label == nil {
label = labels.Everything()
}
list := &v1beta1.ReplicaSetList{}
list := &v1beta1.ReplicaSetList{ListMeta: obj.(*v1beta1.ReplicaSetList).ListMeta}
for _, item := range obj.(*v1beta1.ReplicaSetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeNetworkPolicies) List(opts v1.ListOptions) (result *networking_v1.N
if label == nil {
label = labels.Everything()
}
list := &networking_v1.NetworkPolicyList{}
list := &networking_v1.NetworkPolicyList{ListMeta: obj.(*networking_v1.NetworkPolicyList).ListMeta}
for _, item := range obj.(*networking_v1.NetworkPolicyList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakePodDisruptionBudgets) List(opts v1.ListOptions) (result *v1beta1.Po
if label == nil {
label = labels.Everything()
}
list := &v1beta1.PodDisruptionBudgetList{}
list := &v1beta1.PodDisruptionBudgetList{ListMeta: obj.(*v1beta1.PodDisruptionBudgetList).ListMeta}
for _, item := range obj.(*v1beta1.PodDisruptionBudgetList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakePodSecurityPolicies) List(opts v1.ListOptions) (result *v1beta1.Pod
if label == nil {
label = labels.Everything()
}
list := &v1beta1.PodSecurityPolicyList{}
list := &v1beta1.PodSecurityPolicyList{ListMeta: obj.(*v1beta1.PodSecurityPolicyList).ListMeta}
for _, item := range obj.(*v1beta1.PodSecurityPolicyList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *rbac_v1.ClusterRol
if label == nil {
label = labels.Everything()
}
list := &rbac_v1.ClusterRoleList{}
list := &rbac_v1.ClusterRoleList{ListMeta: obj.(*rbac_v1.ClusterRoleList).ListMeta}
for _, item := range obj.(*rbac_v1.ClusterRoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *rbac_v1.Clu
if label == nil {
label = labels.Everything()
}
list := &rbac_v1.ClusterRoleBindingList{}
list := &rbac_v1.ClusterRoleBindingList{ListMeta: obj.(*rbac_v1.ClusterRoleBindingList).ListMeta}
for _, item := range obj.(*rbac_v1.ClusterRoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *rbac_v1.RoleList, err err
if label == nil {
label = labels.Everything()
}
list := &rbac_v1.RoleList{}
list := &rbac_v1.RoleList{ListMeta: obj.(*rbac_v1.RoleList).ListMeta}
for _, item := range obj.(*rbac_v1.RoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *rbac_v1.RoleBindin
if label == nil {
label = labels.Everything()
}
list := &rbac_v1.RoleBindingList{}
list := &rbac_v1.RoleBindingList{ListMeta: obj.(*rbac_v1.RoleBindingList).ListMeta}
for _, item := range obj.(*rbac_v1.RoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1alpha1.ClusterRo
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.ClusterRoleList{}
list := &v1alpha1.ClusterRoleList{ListMeta: obj.(*v1alpha1.ClusterRoleList).ListMeta}
for _, item := range obj.(*v1alpha1.ClusterRoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.Cl
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.ClusterRoleBindingList{}
list := &v1alpha1.ClusterRoleBindingList{ListMeta: obj.(*v1alpha1.ClusterRoleBindingList).ListMeta}
for _, item := range obj.(*v1alpha1.ClusterRoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *v1alpha1.RoleList, err er
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.RoleList{}
list := &v1alpha1.RoleList{ListMeta: obj.(*v1alpha1.RoleList).ListMeta}
for _, item := range obj.(*v1alpha1.RoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1alpha1.RoleBindi
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.RoleBindingList{}
list := &v1alpha1.RoleBindingList{ListMeta: obj.(*v1alpha1.RoleBindingList).ListMeta}
for _, item := range obj.(*v1alpha1.RoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeClusterRoles) List(opts v1.ListOptions) (result *v1beta1.ClusterRol
if label == nil {
label = labels.Everything()
}
list := &v1beta1.ClusterRoleList{}
list := &v1beta1.ClusterRoleList{ListMeta: obj.(*v1beta1.ClusterRoleList).ListMeta}
for _, item := range obj.(*v1beta1.ClusterRoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakeClusterRoleBindings) List(opts v1.ListOptions) (result *v1beta1.Clu
if label == nil {
label = labels.Everything()
}
list := &v1beta1.ClusterRoleBindingList{}
list := &v1beta1.ClusterRoleBindingList{ListMeta: obj.(*v1beta1.ClusterRoleBindingList).ListMeta}
for _, item := range obj.(*v1beta1.ClusterRoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeRoles) List(opts v1.ListOptions) (result *v1beta1.RoleList, err err
if label == nil {
label = labels.Everything()
}
list := &v1beta1.RoleList{}
list := &v1beta1.RoleList{ListMeta: obj.(*v1beta1.RoleList).ListMeta}
for _, item := range obj.(*v1beta1.RoleList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -62,7 +62,7 @@ func (c *FakeRoleBindings) List(opts v1.ListOptions) (result *v1beta1.RoleBindin
if label == nil {
label = labels.Everything()
}
list := &v1beta1.RoleBindingList{}
list := &v1beta1.RoleBindingList{ListMeta: obj.(*v1beta1.RoleBindingList).ListMeta}
for _, item := range obj.(*v1beta1.RoleBindingList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -59,7 +59,7 @@ func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1alpha1.Priori
if label == nil {
label = labels.Everything()
}
list := &v1alpha1.PriorityClassList{}
list := &v1alpha1.PriorityClassList{ListMeta: obj.(*v1alpha1.PriorityClassList).ListMeta}
for _, item := range obj.(*v1alpha1.PriorityClassList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)

View File

@@ -0,0 +1,20 @@
/*
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 v1beta1

View File

@@ -0,0 +1,20 @@
/*
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

View File

@@ -0,0 +1,120 @@
/*
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 (
v1beta1 "k8s.io/api/scheduling/v1beta1"
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"
)
// FakePriorityClasses implements PriorityClassInterface
type FakePriorityClasses struct {
Fake *FakeSchedulingV1beta1
}
var priorityclassesResource = schema.GroupVersionResource{Group: "scheduling.k8s.io", Version: "v1beta1", Resource: "priorityclasses"}
var priorityclassesKind = schema.GroupVersionKind{Group: "scheduling.k8s.io", Version: "v1beta1", Kind: "PriorityClass"}
// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any.
func (c *FakePriorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(priorityclassesResource, name), &v1beta1.PriorityClass{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PriorityClass), err
}
// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors.
func (c *FakePriorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(priorityclassesResource, priorityclassesKind, opts), &v1beta1.PriorityClassList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1beta1.PriorityClassList{ListMeta: obj.(*v1beta1.PriorityClassList).ListMeta}
for _, item := range obj.(*v1beta1.PriorityClassList).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 priorityClasses.
func (c *FakePriorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(priorityclassesResource, opts))
}
// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any.
func (c *FakePriorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PriorityClass), err
}
// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any.
func (c *FakePriorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(priorityclassesResource, priorityClass), &v1beta1.PriorityClass{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PriorityClass), err
}
// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs.
func (c *FakePriorityClasses) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(priorityclassesResource, name), &v1beta1.PriorityClass{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakePriorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(priorityclassesResource, listOptions)
_, err := c.Fake.Invokes(action, &v1beta1.PriorityClassList{})
return err
}
// Patch applies the patch and returns the patched priorityClass.
func (c *FakePriorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(priorityclassesResource, name, data, subresources...), &v1beta1.PriorityClass{})
if obj == nil {
return nil, err
}
return obj.(*v1beta1.PriorityClass), err
}

View File

@@ -0,0 +1,40 @@
/*
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 (
v1beta1 "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1"
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
)
type FakeSchedulingV1beta1 struct {
*testing.Fake
}
func (c *FakeSchedulingV1beta1) PriorityClasses() v1beta1.PriorityClassInterface {
return &FakePriorityClasses{c}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeSchedulingV1beta1) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -1,4 +1,5 @@
Copyright 2011-2016 Canonical Ltd.
/*
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.
@@ -11,3 +12,10 @@ 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 v1beta1
type PriorityClassExpansion interface{}

View File

@@ -0,0 +1,147 @@
/*
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 v1beta1
import (
v1beta1 "k8s.io/api/scheduling/v1beta1"
v1 "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"
)
// PriorityClassesGetter has a method to return a PriorityClassInterface.
// A group's client should implement this interface.
type PriorityClassesGetter interface {
PriorityClasses() PriorityClassInterface
}
// PriorityClassInterface has methods to work with PriorityClass resources.
type PriorityClassInterface interface {
Create(*v1beta1.PriorityClass) (*v1beta1.PriorityClass, error)
Update(*v1beta1.PriorityClass) (*v1beta1.PriorityClass, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1beta1.PriorityClass, error)
List(opts v1.ListOptions) (*v1beta1.PriorityClassList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error)
PriorityClassExpansion
}
// priorityClasses implements PriorityClassInterface
type priorityClasses struct {
client rest.Interface
}
// newPriorityClasses returns a PriorityClasses
func newPriorityClasses(c *SchedulingV1beta1Client) *priorityClasses {
return &priorityClasses{
client: c.RESTClient(),
}
}
// Get takes name of the priorityClass, and returns the corresponding priorityClass object, and an error if there is any.
func (c *priorityClasses) Get(name string, options v1.GetOptions) (result *v1beta1.PriorityClass, err error) {
result = &v1beta1.PriorityClass{}
err = c.client.Get().
Resource("priorityclasses").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of PriorityClasses that match those selectors.
func (c *priorityClasses) List(opts v1.ListOptions) (result *v1beta1.PriorityClassList, err error) {
result = &v1beta1.PriorityClassList{}
err = c.client.Get().
Resource("priorityclasses").
VersionedParams(&opts, scheme.ParameterCodec).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested priorityClasses.
func (c *priorityClasses) Watch(opts v1.ListOptions) (watch.Interface, error) {
opts.Watch = true
return c.client.Get().
Resource("priorityclasses").
VersionedParams(&opts, scheme.ParameterCodec).
Watch()
}
// Create takes the representation of a priorityClass and creates it. Returns the server's representation of the priorityClass, and an error, if there is any.
func (c *priorityClasses) Create(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) {
result = &v1beta1.PriorityClass{}
err = c.client.Post().
Resource("priorityclasses").
Body(priorityClass).
Do().
Into(result)
return
}
// Update takes the representation of a priorityClass and updates it. Returns the server's representation of the priorityClass, and an error, if there is any.
func (c *priorityClasses) Update(priorityClass *v1beta1.PriorityClass) (result *v1beta1.PriorityClass, err error) {
result = &v1beta1.PriorityClass{}
err = c.client.Put().
Resource("priorityclasses").
Name(priorityClass.Name).
Body(priorityClass).
Do().
Into(result)
return
}
// Delete takes name of the priorityClass and deletes it. Returns an error if one occurs.
func (c *priorityClasses) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Resource("priorityclasses").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *priorityClasses) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
return c.client.Delete().
Resource("priorityclasses").
VersionedParams(&listOptions, scheme.ParameterCodec).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched priorityClass.
func (c *priorityClasses) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.PriorityClass, err error) {
result = &v1beta1.PriorityClass{}
err = c.client.Patch(pt).
Resource("priorityclasses").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -0,0 +1,90 @@
/*
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 v1beta1
import (
v1beta1 "k8s.io/api/scheduling/v1beta1"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/kubernetes/scheme"
rest "k8s.io/client-go/rest"
)
type SchedulingV1beta1Interface interface {
RESTClient() rest.Interface
PriorityClassesGetter
}
// SchedulingV1beta1Client is used to interact with features provided by the scheduling.k8s.io group.
type SchedulingV1beta1Client struct {
restClient rest.Interface
}
func (c *SchedulingV1beta1Client) PriorityClasses() PriorityClassInterface {
return newPriorityClasses(c)
}
// NewForConfig creates a new SchedulingV1beta1Client for the given config.
func NewForConfig(c *rest.Config) (*SchedulingV1beta1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &SchedulingV1beta1Client{client}, nil
}
// NewForConfigOrDie creates a new SchedulingV1beta1Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *SchedulingV1beta1Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new SchedulingV1beta1Client for the given RESTClient.
func New(c rest.Interface) *SchedulingV1beta1Client {
return &SchedulingV1beta1Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1beta1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
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 *SchedulingV1beta1Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

Some files were not shown because too many files have changed in this diff Show More